merge with revision 1294 where issues with SHIFT operations on Long were detected arithmetic
authorMartin Soch <Martin.Soch@oracle.com>
Mon, 07 Oct 2013 14:20:58 +0200
brancharithmetic
changeset 1351f73c1a0234fb
parent 783 8264f07b1f46
parent 1294 70532b5324e2
child 1352 7bc78045adfd
merge with revision 1294 where issues with SHIFT operations on Long were detected
rt/emul/compact/src/main/java/java/lang/System.java
rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar
rt/javap/pom.xml
rt/javap/src/main/java/org/apidesign/javap/AnnotationParser.java
rt/javap/src/main/java/org/apidesign/javap/AttrData.java
rt/javap/src/main/java/org/apidesign/javap/CPX.java
rt/javap/src/main/java/org/apidesign/javap/CPX2.java
rt/javap/src/main/java/org/apidesign/javap/ClassData.java
rt/javap/src/main/java/org/apidesign/javap/Constants.java
rt/javap/src/main/java/org/apidesign/javap/FieldData.java
rt/javap/src/main/java/org/apidesign/javap/Hashtable.java
rt/javap/src/main/java/org/apidesign/javap/InnerClassData.java
rt/javap/src/main/java/org/apidesign/javap/LineNumData.java
rt/javap/src/main/java/org/apidesign/javap/LocVarData.java
rt/javap/src/main/java/org/apidesign/javap/MethodData.java
rt/javap/src/main/java/org/apidesign/javap/RuntimeConstants.java
rt/javap/src/main/java/org/apidesign/javap/StackMapData.java
rt/javap/src/main/java/org/apidesign/javap/StackMapIterator.java
rt/javap/src/main/java/org/apidesign/javap/StackMapTableData.java
rt/javap/src/main/java/org/apidesign/javap/TrapData.java
rt/javap/src/main/java/org/apidesign/javap/TrapDataIterator.java
rt/javap/src/main/java/org/apidesign/javap/TypeArray.java
rt/javap/src/main/java/org/apidesign/javap/Vector.java
rt/launcher/pom.xml
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java
rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java
rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml
rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java
rt/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml
rt/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml
rt/mojo/src/main/resources/archetype-resources/nbactions.xml
rt/mojo/src/main/resources/archetype-resources/pom.xml
rt/mojo/src/main/resources/archetype-resources/src/main/java/App.java
rt/mojo/src/main/resources/archetype-resources/src/main/resources/index.html
rt/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java
rt/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java
rt/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java
rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java
rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe
rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt
     1.1 --- a/.hgtags	Wed Feb 27 17:50:47 2013 +0100
     1.2 +++ b/.hgtags	Mon Oct 07 14:20:58 2013 +0200
     1.3 @@ -1,1 +1,13 @@
     1.4  0a115f1c6f3c70458fc479ae82b4d7fcdeb7e95a jdk7-b147_base
     1.5 +7367a296a9ec4a88e0292a41244c96283818e563 bck2brwsr-0.3
     1.6 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
     1.7 +30e9ac29654fba6f67d0921e7e3aa21133442592 release-0.5
     1.8 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-0.4
     1.9 +caf1e66268fd4100d57922d973ae09a6bf3be847 release-${releaseVersion}
    1.10 +0000000000000000000000000000000000000000 release-${releaseVersion}
    1.11 +52a4a5f868bccc67d50ad17f793b9ebabdf75d88 release-0.6
    1.12 +6792dc0bafb9c76a099e45bfc9e967d6a2823827 release-0.7
    1.13 +623816269b75e53fffb4b19960df7040a3c20056 release-0.7
    1.14 +23572dc719bd630817d11eaabdee4565f63ef8e1 release-0.7.1
    1.15 +56abd247f421febd8b2c5e59d666968692e11555 release-0.7.2
    1.16 +a83e16b8b825399bb21461e578c32d86982e4ed3 release-0.8
     2.1 --- a/benchmarks/matrix-multiplication/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     2.2 +++ b/benchmarks/matrix-multiplication/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     2.3 @@ -1,16 +1,15 @@
     2.4  <?xml version="1.0"?>
     2.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     2.6 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     2.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     2.8    <modelVersion>4.0.0</modelVersion>
     2.9  
    2.10    <groupId>org.apidesign.bck2brwsr</groupId>
    2.11    <artifactId>matrix.multiplication</artifactId>
    2.12 -  <version>0.3-SNAPSHOT</version>
    2.13 +  <version>0.9-SNAPSHOT</version>
    2.14    <packaging>jar</packaging>
    2.15    <parent>
    2.16      <artifactId>benchmarks</artifactId>
    2.17      <groupId>org.apidesign.bck2brwsr</groupId>
    2.18 -    <version>0.3-SNAPSHOT</version>
    2.19 +    <version>0.9-SNAPSHOT</version>
    2.20    </parent>
    2.21  
    2.22    <name>Matrix multiplication</name>
    2.23 @@ -38,6 +37,36 @@
    2.24                    <skip>true</skip>
    2.25                </configuration>
    2.26            </plugin>      
    2.27 +          <plugin>
    2.28 +              <groupId>org.codehaus.mojo</groupId>
    2.29 +              <artifactId>xml-maven-plugin</artifactId>
    2.30 +              <version>1.0</version>
    2.31 +              <executions>
    2.32 +                  <execution>
    2.33 +                      <goals>
    2.34 +                          <goal>transform</goal>
    2.35 +                      </goals>
    2.36 +                      <phase>install</phase>
    2.37 +                  </execution>
    2.38 +              </executions>
    2.39 +              <configuration>
    2.40 +                  <transformationSets>
    2.41 +                      <transformationSet>
    2.42 +                          <dir>target/surefire-reports</dir>
    2.43 +                          <outputDir>target/surefire-reports</outputDir>
    2.44 +                          <includes>
    2.45 +                              <include>TEST*.xml</include>
    2.46 +                          </includes>
    2.47 +                          <stylesheet>src/main/select-time.xsl</stylesheet>
    2.48 +                          <fileMappers>
    2.49 +                              <fileMapper implementation="org.codehaus.plexus.components.io.filemappers.FileExtensionMapper">
    2.50 +                                  <targetExtension>.csv</targetExtension>
    2.51 +                              </fileMapper>
    2.52 +                          </fileMappers>                          
    2.53 +                      </transformationSet>
    2.54 +                  </transformationSets>
    2.55 +              </configuration>
    2.56 +          </plugin>
    2.57        </plugins>
    2.58    </build>
    2.59    
    2.60 @@ -45,7 +74,7 @@
    2.61      <dependency>
    2.62        <groupId>org.apidesign.bck2brwsr</groupId>
    2.63        <artifactId>emul.mini</artifactId>
    2.64 -      <version>0.3-SNAPSHOT</version>
    2.65 +      <version>0.9-SNAPSHOT</version>
    2.66      </dependency>
    2.67      <dependency>
    2.68        <groupId>org.testng</groupId>
    2.69 @@ -62,7 +91,13 @@
    2.70      <dependency>
    2.71        <groupId>org.apidesign.bck2brwsr</groupId>
    2.72        <artifactId>vmtest</artifactId>
    2.73 -      <version>0.3-SNAPSHOT</version>
    2.74 +      <version>0.9-SNAPSHOT</version>
    2.75 +      <scope>test</scope>
    2.76 +    </dependency>
    2.77 +    <dependency>
    2.78 +      <groupId>org.apidesign.bck2brwsr</groupId>
    2.79 +      <artifactId>launcher.http</artifactId>
    2.80 +      <version>0.9-SNAPSHOT</version>
    2.81        <scope>test</scope>
    2.82      </dependency>
    2.83    </dependencies>
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/benchmarks/matrix-multiplication/src/main/select-time.xsl	Mon Oct 07 14:20:58 2013 +0200
     3.3 @@ -0,0 +1,55 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<!--
     3.6 +
     3.7 +    Back 2 Browser Bytecode Translator
     3.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     3.9 +
    3.10 +    This program is free software: you can redistribute it and/or modify
    3.11 +    it under the terms of the GNU General Public License as published by
    3.12 +    the Free Software Foundation, version 2 of the License.
    3.13 +
    3.14 +    This program is distributed in the hope that it will be useful,
    3.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    3.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    3.17 +    GNU General Public License for more details.
    3.18 +
    3.19 +    You should have received a copy of the GNU General Public License
    3.20 +    along with this program. Look for COPYING file in the top folder.
    3.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    3.22 +
    3.23 +-->
    3.24 +
    3.25 +<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    3.26 +    <xsl:output method="text"/>
    3.27 +
    3.28 +    <xsl:template match="/">
    3.29 +        <xsl:apply-templates mode="header" select="testsuite/testcase"/><xsl:text>End
    3.30 +</xsl:text>
    3.31 +        <xsl:apply-templates mode="value" select="testsuite/testcase"/><xsl:text>NaN
    3.32 +</xsl:text>
    3.33 +    </xsl:template>
    3.34 +        
    3.35 +    
    3.36 +    <xsl:template match="testcase" mode="header">
    3.37 +      <xsl:if test="contains(@name,'tenThousand')">
    3.38 +        <xsl:if test="not(contains(@name, '[Java]'))">
    3.39 +          <xsl:if test="not(contains(@name, '[Compare'))">
    3.40 +              <xsl:value-of select="@name"/>
    3.41 +              <xsl:text>,</xsl:text>
    3.42 +          </xsl:if>
    3.43 +        </xsl:if>
    3.44 +      </xsl:if>
    3.45 +    </xsl:template>
    3.46 +
    3.47 +    <xsl:template match="testcase" mode="value">
    3.48 +      <xsl:if test="contains(@name,'tenThousand')">
    3.49 +        <xsl:if test="not(contains(@name, '[Java]'))">
    3.50 +          <xsl:if test="not(contains(@name, '[Compare'))">
    3.51 +            <xsl:value-of select="@time"/>
    3.52 +            <xsl:text>,</xsl:text>
    3.53 +          </xsl:if>
    3.54 +        </xsl:if>
    3.55 +      </xsl:if>
    3.56 +    </xsl:template>
    3.57 +
    3.58 +</xsl:stylesheet>
     4.1 --- a/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java	Wed Feb 27 17:50:47 2013 +0100
     4.2 +++ b/benchmarks/matrix-multiplication/src/test/java/org/apidesign/benchmark/matrixmul/MatrixTest.java	Mon Oct 07 14:20:58 2013 +0200
     4.3 @@ -31,6 +31,22 @@
     4.4      }
     4.5  
     4.6      @Compare(scripting = false) 
     4.7 +    public String oneIteration() throws IOException {
     4.8 +    
     4.9 +        Matrix m1 = new Matrix(5);
    4.10 +        Matrix m2 = new Matrix(5);
    4.11 +        
    4.12 +        m1.generateData();
    4.13 +        m2.generateData();
    4.14 +        
    4.15 +        Matrix res = m1.multiply(m2);
    4.16 +        
    4.17 +        StringBuilder sb = new StringBuilder();
    4.18 +        res.printOn(sb);
    4.19 +        return sb.toString();
    4.20 +    }
    4.21 +    
    4.22 +    @Compare(scripting = false) 
    4.23      public String tenThousandIterations() throws IOException {
    4.24      
    4.25          Matrix m1 = new Matrix(5);
    4.26 @@ -50,6 +66,27 @@
    4.27          return sb.toString();
    4.28      }
    4.29      
    4.30 +    @Compare(scripting = false) 
    4.31 +    public String tenUselessIterations() throws IOException {
    4.32 +    
    4.33 +        Matrix m1 = new Matrix(5);
    4.34 +        Matrix m2 = new Matrix(5);
    4.35 +        
    4.36 +        m1.generateData();
    4.37 +        m2.generateData();
    4.38 +        
    4.39 +        Matrix res = null;
    4.40 +        for (int i = 0; i < 10; i++) {
    4.41 +            res = m1.multiply(m2);
    4.42 +            m1 = res;
    4.43 +        }
    4.44 +        
    4.45 +        StringBuilder sb = new StringBuilder();
    4.46 +        res.printOn(sb);
    4.47 +        return sb.toString();
    4.48 +    }
    4.49 +
    4.50 +    
    4.51      @Factory
    4.52      public static Object[] create() {
    4.53          return VMTest.create(MatrixTest.class);
     5.1 --- a/benchmarks/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     5.2 +++ b/benchmarks/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     5.3 @@ -4,11 +4,11 @@
     5.4    <parent>
     5.5      <artifactId>bck2brwsr</artifactId>
     5.6      <groupId>org.apidesign</groupId>
     5.7 -    <version>0.3-SNAPSHOT</version>
     5.8 +    <version>0.9-SNAPSHOT</version>
     5.9    </parent>
    5.10    <groupId>org.apidesign.bck2brwsr</groupId>
    5.11    <artifactId>benchmarks</artifactId>
    5.12 -  <version>0.3-SNAPSHOT</version>
    5.13 +  <version>0.9-SNAPSHOT</version>
    5.14    <packaging>pom</packaging>
    5.15    <name>Performance benchmarks</name>
    5.16    <modules>
     6.1 --- a/dew/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     6.2 +++ b/dew/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     6.3 @@ -1,15 +1,14 @@
     6.4  <?xml version="1.0"?>
     6.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
     6.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     6.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     6.8    <modelVersion>4.0.0</modelVersion>
     6.9    <parent>
    6.10      <groupId>org.apidesign</groupId>
    6.11      <artifactId>bck2brwsr</artifactId>
    6.12 -    <version>0.3-SNAPSHOT</version>
    6.13 +    <version>0.9-SNAPSHOT</version>
    6.14    </parent>
    6.15    <groupId>org.apidesign.bck2brwsr</groupId>
    6.16    <artifactId>dew</artifactId>
    6.17 -  <version>0.3-SNAPSHOT</version>
    6.18 +  <version>0.9-SNAPSHOT</version>
    6.19    <name>Development Environment for Web</name>
    6.20    <url>http://maven.apache.org</url>
    6.21      <build>
    6.22 @@ -38,11 +37,19 @@
    6.23                      <executable>java</executable>
    6.24                       <arguments>
    6.25                          <argument>-classpath</argument>
    6.26 -                        <classpath/>
    6.27 +                        <classpath />
    6.28                          <argument>org.apidesign.bck2brwsr.dew.Dew</argument>
    6.29                      </arguments>
    6.30                  </configuration>
    6.31              </plugin>
    6.32 +            <plugin>
    6.33 +                <groupId>org.apache.maven.plugins</groupId>
    6.34 +                <artifactId>maven-deploy-plugin</artifactId>
    6.35 +                <version>2.7</version>
    6.36 +                <configuration>
    6.37 +                    <skip>true</skip>
    6.38 +                </configuration>
    6.39 +            </plugin>      
    6.40          </plugins>
    6.41      </build>
    6.42      <properties>
     7.1 --- a/ide/editor/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     7.2 +++ b/ide/editor/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     7.3 @@ -4,19 +4,18 @@
     7.4      <parent>
     7.5          <artifactId>ide</artifactId>
     7.6          <groupId>org.apidesign.bck2brwsr</groupId>
     7.7 -        <version>0.3-SNAPSHOT</version>
     7.8 +        <version>0.9-SNAPSHOT</version>
     7.9      </parent>
    7.10  
    7.11 -    <groupId>org.apidesign.bck2brwsr.ide.editor</groupId>
    7.12 +    <groupId>org.apidesign.bck2brwsr.ide</groupId>
    7.13      <artifactId>editor</artifactId>
    7.14 -    <version>0.3-SNAPSHOT</version>
    7.15 +    <version>0.9-SNAPSHOT</version>
    7.16      <packaging>nbm</packaging>
    7.17  
    7.18      <name>Editor Support for Bck2Brwsr</name>
    7.19  
    7.20      <properties>
    7.21          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    7.22 -        <netbeans.version>RELEASE72</netbeans.version>
    7.23          <endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
    7.24      </properties>
    7.25  
    7.26 @@ -40,71 +39,59 @@
    7.27          <dependency>
    7.28              <groupId>org.netbeans.api</groupId>
    7.29              <artifactId>org-netbeans-api-annotations-common</artifactId>
    7.30 -            <version>${netbeans.version}</version>
    7.31          </dependency>
    7.32          <dependency>
    7.33              <groupId>org.netbeans.api</groupId>
    7.34              <artifactId>org-netbeans-modules-java-source</artifactId>
    7.35 -            <version>${netbeans.version}</version>
    7.36          </dependency>
    7.37          <dependency>
    7.38              <groupId>org.netbeans.api</groupId>
    7.39              <artifactId>org-netbeans-libs-javacapi</artifactId>
    7.40 -            <version>${netbeans.version}</version>
    7.41          </dependency>
    7.42          <dependency>
    7.43              <groupId>org.netbeans.api</groupId>
    7.44              <artifactId>org-netbeans-spi-java-hints</artifactId>
    7.45 -            <version>${netbeans.version}</version>
    7.46          </dependency>
    7.47          <dependency>
    7.48              <groupId>org.netbeans.api</groupId>
    7.49              <artifactId>org-netbeans-modules-parsing-api</artifactId>
    7.50 -            <version>${netbeans.version}</version>
    7.51          </dependency>
    7.52          <dependency>
    7.53              <groupId>org.netbeans.api</groupId>
    7.54              <artifactId>org-netbeans-spi-editor-hints</artifactId>
    7.55 -            <version>${netbeans.version}</version>
    7.56          </dependency>
    7.57          <dependency>
    7.58              <groupId>org.netbeans.api</groupId>
    7.59              <artifactId>org-openide-util</artifactId>
    7.60 -            <version>${netbeans.version}</version>
    7.61          </dependency>
    7.62          <dependency>
    7.63              <groupId>org.netbeans.api</groupId>
    7.64              <artifactId>org-netbeans-modules-java-lexer</artifactId>
    7.65 -            <version>${netbeans.version}</version>
    7.66          </dependency>
    7.67          <dependency>
    7.68              <groupId>org.netbeans.api</groupId>
    7.69              <artifactId>org-netbeans-modules-lexer</artifactId>
    7.70 -            <version>${netbeans.version}</version>
    7.71          </dependency>
    7.72          <dependency>
    7.73              <groupId>org.apidesign.bck2brwsr</groupId>
    7.74              <artifactId>core</artifactId>
    7.75 -            <version>0.3-SNAPSHOT</version>
    7.76 +            <version>0.9-SNAPSHOT</version>
    7.77              <type>jar</type>
    7.78              <scope>test</scope>
    7.79          </dependency>
    7.80          <dependency>
    7.81              <groupId>org.netbeans.api</groupId>
    7.82              <artifactId>org-netbeans-modules-java-hints-test</artifactId>
    7.83 -            <version>${netbeans.version}</version>
    7.84              <scope>test</scope>
    7.85          </dependency>
    7.86          <dependency>
    7.87              <groupId>org.netbeans.api</groupId>
    7.88              <artifactId>org-netbeans-libs-junit4</artifactId>
    7.89 -            <version>${netbeans.version}</version>
    7.90              <scope>test</scope>
    7.91          </dependency>
    7.92          <dependency>
    7.93              <groupId>org.netbeans.modules</groupId>
    7.94              <artifactId>org-netbeans-lib-nbjavac</artifactId>
    7.95 -            <version>${netbeans.version}</version>
    7.96              <scope>test</scope>
    7.97          </dependency>
    7.98          <dependency>
     8.1 --- a/ide/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     8.2 +++ b/ide/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     8.3 @@ -4,14 +4,26 @@
     8.4    <parent>
     8.5      <artifactId>bck2brwsr</artifactId>
     8.6      <groupId>org.apidesign</groupId>
     8.7 -    <version>0.3-SNAPSHOT</version>
     8.8 +    <version>0.9-SNAPSHOT</version>
     8.9    </parent>
    8.10    <groupId>org.apidesign.bck2brwsr</groupId>
    8.11    <artifactId>ide</artifactId>
    8.12 -  <version>0.3-SNAPSHOT</version>
    8.13 +  <version>0.9-SNAPSHOT</version>
    8.14    <packaging>pom</packaging>
    8.15    <name>IDE Support</name>
    8.16    <modules>
    8.17      <module>editor</module>
    8.18    </modules>
    8.19 +  <build>
    8.20 +      <plugins>
    8.21 +          <plugin>
    8.22 +              <groupId>org.apache.maven.plugins</groupId>
    8.23 +              <artifactId>maven-deploy-plugin</artifactId>
    8.24 +              <version>2.7</version>
    8.25 +              <configuration>
    8.26 +                  <skip>true</skip>
    8.27 +              </configuration>
    8.28 +          </plugin>      
    8.29 +      </plugins>
    8.30 +  </build>
    8.31  </project>
     9.1 --- a/javaquery/api/pom.xml	Wed Feb 27 17:50:47 2013 +0100
     9.2 +++ b/javaquery/api/pom.xml	Mon Oct 07 14:20:58 2013 +0200
     9.3 @@ -1,15 +1,14 @@
     9.4  <?xml version="1.0"?>
     9.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
     9.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     9.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     9.8    <modelVersion>4.0.0</modelVersion>
     9.9    <parent>
    9.10      <groupId>org.apidesign.bck2brwsr</groupId>
    9.11      <artifactId>javaquery</artifactId>
    9.12 -    <version>0.3-SNAPSHOT</version>
    9.13 +    <version>0.9-SNAPSHOT</version>
    9.14    </parent>
    9.15    <groupId>org.apidesign.bck2brwsr</groupId>
    9.16    <artifactId>javaquery.api</artifactId>
    9.17 -  <version>0.3-SNAPSHOT</version>
    9.18 +  <version>0.9-SNAPSHOT</version>
    9.19    <name>JavaQuery API</name>
    9.20    <url>http://maven.apache.org</url>
    9.21      <build>
    9.22 @@ -19,8 +18,16 @@
    9.23                  <artifactId>maven-compiler-plugin</artifactId>
    9.24                  <version>2.3.2</version>
    9.25                  <configuration>
    9.26 -                    <source>1.6</source>
    9.27 -                    <target>1.6</target>
    9.28 +                    <source>1.7</source>
    9.29 +                    <target>1.7</target>
    9.30 +                </configuration>
    9.31 +            </plugin>
    9.32 +            <plugin>
    9.33 +                <groupId>org.apache.maven.plugins</groupId>
    9.34 +                <artifactId>maven-javadoc-plugin</artifactId>
    9.35 +                <configuration>
    9.36 +                    <subpackages>org.apidesign.bck2brwsr.htmlpage.api</subpackages>
    9.37 +                    <skip>false</skip>
    9.38                  </configuration>
    9.39              </plugin>
    9.40          </plugins>
    9.41 @@ -66,5 +73,11 @@
    9.42        <version>${project.version}</version>
    9.43        <scope>test</scope>
    9.44      </dependency>
    9.45 +    <dependency>
    9.46 +      <groupId>${project.groupId}</groupId>
    9.47 +      <artifactId>launcher.http</artifactId>
    9.48 +      <version>${project.version}</version>
    9.49 +      <scope>test</scope>
    9.50 +    </dependency>    
    9.51    </dependencies>
    9.52  </project>
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypes.java	Mon Oct 07 14:20:58 2013 +0200
    10.3 @@ -0,0 +1,155 @@
    10.4 +/**
    10.5 + * Back 2 Browser Bytecode Translator
    10.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.7 + *
    10.8 + * This program is free software: you can redistribute it and/or modify
    10.9 + * it under the terms of the GNU General Public License as published by
   10.10 + * the Free Software Foundation, version 2 of the License.
   10.11 + *
   10.12 + * This program is distributed in the hope that it will be useful,
   10.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.15 + * GNU General Public License for more details.
   10.16 + *
   10.17 + * You should have received a copy of the GNU General Public License
   10.18 + * along with this program. Look for COPYING file in the top folder.
   10.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   10.20 + */
   10.21 +package org.apidesign.bck2brwsr.htmlpage;
   10.22 +
   10.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   10.24 +
   10.25 +/**
   10.26 + *
   10.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   10.28 + */
   10.29 +public final class ConvertTypes {
   10.30 +    ConvertTypes() {
   10.31 +    }
   10.32 +    
   10.33 +    public static String toString(Object object, String property) {
   10.34 +        Object ret = getProperty(object, property);
   10.35 +        return ret == null ? null : ret.toString();
   10.36 +    }
   10.37 +
   10.38 +    public static double toDouble(Object object, String property) {
   10.39 +        Object ret = getProperty(object, property);
   10.40 +        return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN;
   10.41 +    }
   10.42 +
   10.43 +    public static int toInt(Object object, String property) {
   10.44 +        Object ret = getProperty(object, property);
   10.45 +        return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE;
   10.46 +    }
   10.47 +
   10.48 +    public static <T> T toModel(Class<T> modelClass, Object object, String property) {
   10.49 +        Object ret = getProperty(object, property);
   10.50 +        if (ret == null || modelClass.isInstance(ret)) {
   10.51 +            return modelClass.cast(ret);
   10.52 +        }
   10.53 +        throw new IllegalStateException("Value " + ret + " is not of type " + modelClass);
   10.54 +    }
   10.55 +    
   10.56 +    public static String toJSON(Object value) {
   10.57 +        if (value == null) {
   10.58 +            return "null";
   10.59 +        }
   10.60 +        if (value instanceof Enum) {
   10.61 +            value = value.toString();
   10.62 +        }
   10.63 +        if (value instanceof String) {
   10.64 +            return '"' + 
   10.65 +                ((String)value).
   10.66 +                    replace("\"", "\\\"").
   10.67 +                    replace("\n", "\\n").
   10.68 +                    replace("\r", "\\r").
   10.69 +                    replace("\t", "\\t")
   10.70 +                + '"';
   10.71 +        }
   10.72 +        return value.toString();
   10.73 +    }
   10.74 +    
   10.75 +    @JavaScriptBody(args = { "object", "property" },
   10.76 +        body = "if (property === null) return object;\n"
   10.77 +        + "var p = object[property]; return p ? p : null;"
   10.78 +    )
   10.79 +    private static Object getProperty(Object object, String property) {
   10.80 +        return null;
   10.81 +    }
   10.82 +    
   10.83 +    public static String createJSONP(Object[] jsonResult, Runnable whenDone) {
   10.84 +        int h = whenDone.hashCode();
   10.85 +        String name;
   10.86 +        for (;;) {
   10.87 +            name = "jsonp" + Integer.toHexString(h);
   10.88 +            if (defineIfUnused(name, jsonResult, whenDone)) {
   10.89 +                return name;
   10.90 +            }
   10.91 +            h++;
   10.92 +        }
   10.93 +    }
   10.94 +
   10.95 +    @JavaScriptBody(args = { "name", "arr", "run" }, body = 
   10.96 +        "if (window[name]) return false;\n "
   10.97 +      + "window[name] = function(data) {\n "
   10.98 +      + "  delete window[name];\n"
   10.99 +      + "  var el = window.document.getElementById(name);\n"
  10.100 +      + "  el.parentNode.removeChild(el);\n"
  10.101 +      + "  arr[0] = data;\n"
  10.102 +      + "  run.run__V();\n"
  10.103 +      + "};\n"
  10.104 +      + "return true;\n"
  10.105 +    )
  10.106 +    private static boolean defineIfUnused(String name, Object[] arr, Runnable run) {
  10.107 +        return true;
  10.108 +    }
  10.109 +    
  10.110 +    @JavaScriptBody(args = { "url", "arr", "callback" }, body = ""
  10.111 +        + "var request = new XMLHttpRequest();\n"
  10.112 +        + "request.open('GET', url, true);\n"
  10.113 +        + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n"
  10.114 +        + "request.onreadystatechange = function() {\n"
  10.115 +        + "  if (this.readyState!==4) return;\n"
  10.116 +        + "  try {\n"
  10.117 +        + "    arr[0] = eval('(' + this.response + ')');\n"
  10.118 +        + "  } catch (error) {;\n"
  10.119 +        + "    throw 'Cannot parse' + error + ':' + this.response;\n"
  10.120 +        + "  };\n"
  10.121 +        + "  callback.run__V();\n"
  10.122 +        + "};"
  10.123 +        + "request.send();"
  10.124 +    )
  10.125 +    private static void loadJSON(
  10.126 +        String url, Object[] jsonResult, Runnable whenDone
  10.127 +    ) {
  10.128 +    }
  10.129 +    
  10.130 +    public static void loadJSON(
  10.131 +        String url, Object[] jsonResult, Runnable whenDone, String jsonp
  10.132 +    ) {
  10.133 +        if (jsonp == null) {
  10.134 +            loadJSON(url, jsonResult, whenDone);
  10.135 +        } else {
  10.136 +            loadJSONP(url, jsonp);
  10.137 +        }
  10.138 +    }
  10.139 +    
  10.140 +    @JavaScriptBody(args = { "url", "jsonp" }, body = 
  10.141 +        "var scrpt = window.document.createElement('script');\n "
  10.142 +        + "scrpt.setAttribute('src', url);\n "
  10.143 +        + "scrpt.setAttribute('id', jsonp);\n "
  10.144 +        + "scrpt.setAttribute('type', 'text/javascript');\n "
  10.145 +        + "var body = document.getElementsByTagName('body')[0];\n "
  10.146 +        + "body.appendChild(scrpt);\n"
  10.147 +    )
  10.148 +    private static void loadJSONP(String url, String jsonp) {
  10.149 +        
  10.150 +    }
  10.151 +    
  10.152 +    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
  10.153 +        for (int i = 0; i < props.length; i++) {
  10.154 +            values[i] = getProperty(jsonObject, props[i]);
  10.155 +        }
  10.156 +    }
  10.157 +    
  10.158 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/KOList.java	Mon Oct 07 14:20:58 2013 +0200
    11.3 @@ -0,0 +1,167 @@
    11.4 +/**
    11.5 + * Back 2 Browser Bytecode Translator
    11.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    11.7 + *
    11.8 + * This program is free software: you can redistribute it and/or modify
    11.9 + * it under the terms of the GNU General Public License as published by
   11.10 + * the Free Software Foundation, version 2 of the License.
   11.11 + *
   11.12 + * This program is distributed in the hope that it will be useful,
   11.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.15 + * GNU General Public License for more details.
   11.16 + *
   11.17 + * You should have received a copy of the GNU General Public License
   11.18 + * along with this program. Look for COPYING file in the top folder.
   11.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   11.20 + */
   11.21 +package org.apidesign.bck2brwsr.htmlpage;
   11.22 +
   11.23 +import java.util.ArrayList;
   11.24 +import java.util.Collection;
   11.25 +import java.util.Iterator;
   11.26 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
   11.27 +
   11.28 +/**
   11.29 + *
   11.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   11.31 + */
   11.32 +public final class KOList<T> extends ArrayList<T> {
   11.33 +    private final String name;
   11.34 +    private final String[] deps;
   11.35 +    private Knockout model;
   11.36 +    private Runnable onchange;
   11.37 +
   11.38 +    public KOList(String name, String... deps) {
   11.39 +        this.name = name;
   11.40 +        this.deps = deps;
   11.41 +    }
   11.42 +    
   11.43 +    public void assign(Knockout model) {
   11.44 +        if (this.model != model) {
   11.45 +            this.model = model;
   11.46 +            notifyChange();
   11.47 +        }
   11.48 +    }
   11.49 +    
   11.50 +    public KOList<T> onChange(Runnable r) {
   11.51 +        if (this.onchange != null) {
   11.52 +            throw new IllegalStateException();
   11.53 +        }
   11.54 +        this.onchange = r;
   11.55 +        return this;
   11.56 +    }
   11.57 +
   11.58 +    @Override
   11.59 +    public boolean add(T e) {
   11.60 +        boolean ret = super.add(e);
   11.61 +        notifyChange();
   11.62 +        return ret;
   11.63 +    }
   11.64 +
   11.65 +    @Override
   11.66 +    public boolean addAll(Collection<? extends T> c) {
   11.67 +        boolean ret = super.addAll(c);
   11.68 +        notifyChange();
   11.69 +        return ret;
   11.70 +    }
   11.71 +
   11.72 +    @Override
   11.73 +    public boolean addAll(int index, Collection<? extends T> c) {
   11.74 +        boolean ret = super.addAll(index, c);
   11.75 +        notifyChange();
   11.76 +        return ret;
   11.77 +    }
   11.78 +
   11.79 +    @Override
   11.80 +    public boolean remove(Object o) {
   11.81 +        boolean ret = super.remove(o);
   11.82 +        notifyChange();
   11.83 +        return ret;
   11.84 +    }
   11.85 +
   11.86 +    @Override
   11.87 +    public void clear() {
   11.88 +        super.clear();
   11.89 +        notifyChange();
   11.90 +    }
   11.91 +
   11.92 +    @Override
   11.93 +    public boolean removeAll(Collection<?> c) {
   11.94 +        boolean ret = super.removeAll(c);
   11.95 +        notifyChange();
   11.96 +        return ret;
   11.97 +    }
   11.98 +
   11.99 +    @Override
  11.100 +    public boolean retainAll(Collection<?> c) {
  11.101 +        boolean ret = super.retainAll(c);
  11.102 +        notifyChange();
  11.103 +        return ret;
  11.104 +    }
  11.105 +
  11.106 +    @Override
  11.107 +    public T set(int index, T element) {
  11.108 +        T ret = super.set(index, element);
  11.109 +        notifyChange();
  11.110 +        return ret;
  11.111 +    }
  11.112 +
  11.113 +    @Override
  11.114 +    public void add(int index, T element) {
  11.115 +        super.add(index, element);
  11.116 +        notifyChange();
  11.117 +    }
  11.118 +
  11.119 +    @Override
  11.120 +    public T remove(int index) {
  11.121 +        T ret = super.remove(index);
  11.122 +        notifyChange();
  11.123 +        return ret;
  11.124 +    }
  11.125 +
  11.126 +    @Override
  11.127 +    public String toString() {
  11.128 +        Iterator<T> it = iterator();
  11.129 +        if (!it.hasNext()) {
  11.130 +            return "[]";
  11.131 +        }
  11.132 +        String sep = "";
  11.133 +        StringBuilder sb = new StringBuilder();
  11.134 +        sb.append('[');
  11.135 +        while (it.hasNext()) {
  11.136 +            T t = it.next();
  11.137 +            sb.append(sep);
  11.138 +            sb.append(ConvertTypes.toJSON(t));
  11.139 +            sep = ",";
  11.140 +        }
  11.141 +        sb.append(']');
  11.142 +        return sb.toString();
  11.143 +    }
  11.144 +    
  11.145 +    
  11.146 +    @JavaScriptOnly(name = "koArray", value = "function() { return this.toArray___3Ljava_lang_Object_2(); }")
  11.147 +    private static native int koArray();
  11.148 +
  11.149 +    private void notifyChange() {
  11.150 +        Knockout m = model;
  11.151 +        if (m != null) {
  11.152 +            m.valueHasMutated(name);
  11.153 +            for (String dependant : deps) {
  11.154 +                m.valueHasMutated(dependant);
  11.155 +            }
  11.156 +        }
  11.157 +        Runnable r = onchange;
  11.158 +        if (r != null) {
  11.159 +            r.run();
  11.160 +        }
  11.161 +    }
  11.162 +
  11.163 +    @Override
  11.164 +    public KOList clone() {
  11.165 +        KOList ko = (KOList)super.clone();
  11.166 +        ko.model = null;
  11.167 +        return ko;
  11.168 +    }
  11.169 +    
  11.170 +}
    12.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java	Wed Feb 27 17:50:47 2013 +0100
    12.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java	Mon Oct 07 14:20:58 2013 +0200
    12.3 @@ -18,6 +18,7 @@
    12.4  package org.apidesign.bck2brwsr.htmlpage;
    12.5  
    12.6  import java.lang.reflect.Method;
    12.7 +import java.util.List;
    12.8  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
    12.9  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   12.10  
   12.11 @@ -29,38 +30,40 @@
   12.12  public class Knockout {
   12.13      /** used by tests */
   12.14      static Knockout next;
   12.15 -    
   12.16 -    Knockout() {
   12.17 +    private final Object model;
   12.18 +
   12.19 +    Knockout(Object model) {
   12.20 +        this.model = model == null ? this : model;
   12.21      }
   12.22      
   12.23      public static <M> Knockout applyBindings(
   12.24 -        Class<M> modelClass, M model, String[] propsGettersAndSetters
   12.25 +        Object model, String[] propsGettersAndSetters,
   12.26 +        String[] methodsAndSignatures
   12.27 +    ) {
   12.28 +        applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures);
   12.29 +        return new Knockout(model);
   12.30 +    }
   12.31 +    public static <M> Knockout applyBindings(
   12.32 +        Class<M> modelClass, M model, String[] propsGettersAndSetters,
   12.33 +        String[] methodsAndSignatures
   12.34      ) {
   12.35          Knockout bindings = next;
   12.36          next = null;
   12.37          if (bindings == null) {
   12.38 -            bindings = new Knockout();
   12.39 +            bindings = new Knockout(null);
   12.40          }
   12.41 -        for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
   12.42 -            try {
   12.43 -                Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
   12.44 -                bind(bindings, model, propsGettersAndSetters[i],
   12.45 -                    propsGettersAndSetters[i + 1],
   12.46 -                    propsGettersAndSetters[i + 2],
   12.47 -                    getter.getReturnType().isPrimitive()
   12.48 -                );
   12.49 -            } catch (NoSuchMethodException ex) {
   12.50 -                throw new IllegalStateException(ex.getMessage());
   12.51 -            }
   12.52 -        }
   12.53 +        applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures);
   12.54          applyBindings(bindings);
   12.55          return bindings;
   12.56      }
   12.57  
   12.58 -    @JavaScriptBody(args = { "prop" }, body =
   12.59 -        "this[prop].valueHasMutated();"
   12.60 +    public void valueHasMutated(String prop) {
   12.61 +        valueHasMutated(model, prop);
   12.62 +    }
   12.63 +    @JavaScriptBody(args = { "self", "prop" }, body =
   12.64 +        "self[prop].valueHasMutated();"
   12.65      )
   12.66 -    public void valueHasMutated(String prop) {
   12.67 +    public void valueHasMutated(Object self, String prop) {
   12.68      }
   12.69      
   12.70  
   12.71 @@ -68,26 +71,60 @@
   12.72      public static void triggerEvent(String id, String ev) {
   12.73      }
   12.74      
   12.75 -    @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body =
   12.76 +    @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body =
   12.77            "var bnd = {\n"
   12.78 -        + "  read: function() {\n"
   12.79 +        + "  'read': function() {\n"
   12.80          + "    var v = model[getter]();\n"
   12.81 +        + "    if (array) v = v.koArray();\n"
   12.82          + "    return v;\n"
   12.83          + "  },\n"
   12.84 -        + "  owner: bindings\n"
   12.85 +        + "  'owner': bindings\n"
   12.86          + "};\n"
   12.87          + "if (setter != null) {\n"
   12.88 -        + "  bnd.write = function(val) {\n"
   12.89 +        + "  bnd['write'] = function(val) {\n"
   12.90          + "    model[setter](primitive ? new Number(val) : val);\n"
   12.91          + "  };\n"
   12.92          + "}\n"
   12.93 -        + "bindings[prop] = ko.computed(bnd);"
   12.94 +        + "bindings[prop] = ko['computed'](bnd);"
   12.95      )
   12.96      private static void bind(
   12.97 -        Object bindings, Object model, String prop, String getter, String setter, boolean primitive
   12.98 +        Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array
   12.99 +    ) {
  12.100 +    }
  12.101 +
  12.102 +    @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body = 
  12.103 +        "bindings[prop] = function(data, ev) { model[sig](data, ev); };"
  12.104 +    )
  12.105 +    private static void expose(
  12.106 +        Object bindings, Object model, String prop, String sig
  12.107      ) {
  12.108      }
  12.109      
  12.110      @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  12.111      private static void applyBindings(Object bindings) {}
  12.112 +    
  12.113 +    private static void applyImpl(
  12.114 +        String[] propsGettersAndSetters,
  12.115 +        Class<?> modelClass,
  12.116 +        Object bindings,
  12.117 +        Object model,
  12.118 +        String[] methodsAndSignatures
  12.119 +    ) throws IllegalStateException, SecurityException {
  12.120 +        for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
  12.121 +            try {
  12.122 +                Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
  12.123 +                bind(bindings, model, propsGettersAndSetters[i],
  12.124 +                    propsGettersAndSetters[i + 1],
  12.125 +                    propsGettersAndSetters[i + 2],
  12.126 +                    getter.getReturnType().isPrimitive(),
  12.127 +                    List.class.isAssignableFrom(getter.getReturnType()));
  12.128 +            } catch (NoSuchMethodException ex) {
  12.129 +                throw new IllegalStateException(ex.getMessage());
  12.130 +            }
  12.131 +        }
  12.132 +        for (int i = 0; i < methodsAndSignatures.length; i += 2) {
  12.133 +            expose(
  12.134 +                bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]);
  12.135 +        }
  12.136 +    }
  12.137  }
    13.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Wed Feb 27 17:50:47 2013 +0100
    13.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Mon Oct 07 14:20:58 2013 +0200
    13.3 @@ -20,23 +20,30 @@
    13.4  import java.io.IOException;
    13.5  import java.io.InputStream;
    13.6  import java.io.OutputStreamWriter;
    13.7 +import java.io.StringWriter;
    13.8  import java.io.Writer;
    13.9 +import java.lang.annotation.AnnotationTypeMismatchException;
   13.10 +import java.lang.annotation.IncompleteAnnotationException;
   13.11 +import java.lang.reflect.Method;
   13.12  import java.util.ArrayList;
   13.13  import java.util.Collection;
   13.14  import java.util.Collections;
   13.15  import java.util.HashMap;
   13.16 +import java.util.HashSet;
   13.17  import java.util.LinkedHashSet;
   13.18  import java.util.List;
   13.19 -import java.util.Locale;
   13.20  import java.util.Map;
   13.21  import java.util.Set;
   13.22 +import java.util.WeakHashMap;
   13.23  import javax.annotation.processing.AbstractProcessor;
   13.24  import javax.annotation.processing.Completion;
   13.25  import javax.annotation.processing.Completions;
   13.26 +import javax.annotation.processing.ProcessingEnvironment;
   13.27  import javax.annotation.processing.Processor;
   13.28  import javax.annotation.processing.RoundEnvironment;
   13.29  import javax.annotation.processing.SupportedAnnotationTypes;
   13.30  import javax.lang.model.element.AnnotationMirror;
   13.31 +import javax.lang.model.element.AnnotationValue;
   13.32  import javax.lang.model.element.Element;
   13.33  import javax.lang.model.element.ElementKind;
   13.34  import javax.lang.model.element.ExecutableElement;
   13.35 @@ -44,13 +51,21 @@
   13.36  import javax.lang.model.element.PackageElement;
   13.37  import javax.lang.model.element.TypeElement;
   13.38  import javax.lang.model.element.VariableElement;
   13.39 +import javax.lang.model.type.ArrayType;
   13.40  import javax.lang.model.type.MirroredTypeException;
   13.41 +import javax.lang.model.type.TypeKind;
   13.42  import javax.lang.model.type.TypeMirror;
   13.43 +import javax.lang.model.util.Elements;
   13.44 +import javax.lang.model.util.Types;
   13.45  import javax.tools.Diagnostic;
   13.46  import javax.tools.FileObject;
   13.47  import javax.tools.StandardLocation;
   13.48  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   13.49 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
   13.50  import org.apidesign.bck2brwsr.htmlpage.api.On;
   13.51 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   13.52 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
   13.53 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
   13.54  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   13.55  import org.apidesign.bck2brwsr.htmlpage.api.Property;
   13.56  import org.openide.util.lookup.ServiceProvider;
   13.57 @@ -62,89 +77,70 @@
   13.58   */
   13.59  @ServiceProvider(service=Processor.class)
   13.60  @SupportedAnnotationTypes({
   13.61 +    "org.apidesign.bck2brwsr.htmlpage.api.Model",
   13.62      "org.apidesign.bck2brwsr.htmlpage.api.Page",
   13.63 +    "org.apidesign.bck2brwsr.htmlpage.api.OnFunction",
   13.64 +    "org.apidesign.bck2brwsr.htmlpage.api.OnReceive",
   13.65 +    "org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange",
   13.66 +    "org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty",
   13.67      "org.apidesign.bck2brwsr.htmlpage.api.On"
   13.68  })
   13.69  public final class PageProcessor extends AbstractProcessor {
   13.70 +    private final Map<Element,String> models = new WeakHashMap<>();
   13.71 +    private final Map<Element,Prprt[]> verify = new WeakHashMap<>();
   13.72      @Override
   13.73      public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   13.74 -        for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
   13.75 -            Page p = e.getAnnotation(Page.class);
   13.76 -            if (p == null) {
   13.77 -                continue;
   13.78 -            }
   13.79 -            PackageElement pe = (PackageElement)e.getEnclosingElement();
   13.80 -            String pkg = pe.getQualifiedName().toString();
   13.81 -            
   13.82 -            ProcessPage pp;
   13.83 -            try {
   13.84 -                InputStream is = openStream(pkg, p.xhtml());
   13.85 -                pp = ProcessPage.readPage(is);
   13.86 -                is.close();
   13.87 -            } catch (IOException iOException) {
   13.88 -                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't read " + p.xhtml(), e);
   13.89 -                return false;
   13.90 -            }
   13.91 -            Writer w;
   13.92 -            String className = p.className();
   13.93 -            if (className.isEmpty()) {
   13.94 -                int indx = p.xhtml().indexOf('.');
   13.95 -                className = p.xhtml().substring(0, indx);
   13.96 -            }
   13.97 -            try {
   13.98 -                FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
   13.99 -                w = new OutputStreamWriter(java.openOutputStream());
  13.100 -                try {
  13.101 -                    w.append("package " + pkg + ";\n");
  13.102 -                    w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
  13.103 -                    w.append("final class ").append(className).append(" {\n");
  13.104 -                    w.append("  private boolean locked;\n");
  13.105 -                    if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
  13.106 -                        return false;
  13.107 -                    }
  13.108 -                    for (String id : pp.ids()) {
  13.109 -                        String tag = pp.tagNameForId(id);
  13.110 -                        String type = type(tag);
  13.111 -                        w.append("  ").append("public final ").
  13.112 -                            append(type).append(' ').append(cnstnt(id)).append(" = new ").
  13.113 -                            append(type).append("(\"").append(id).append("\");\n");
  13.114 -                    }
  13.115 -                    List<String> propsGetSet = new ArrayList<String>();
  13.116 -                    Map<String,Collection<String>> propsDeps = new HashMap<String, Collection<String>>();
  13.117 -                    generateComputedProperties(w, e.getEnclosedElements(), propsGetSet, propsDeps);
  13.118 -                    generateProperties(w, p.properties(), propsGetSet, propsDeps);
  13.119 -                    w.append("  private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
  13.120 -                    if (!propsGetSet.isEmpty()) {
  13.121 -                        w.write("public " + className + " applyBindings() {\n");
  13.122 -                        w.write("  ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
  13.123 -                        w.write(className + ".class, this, ");
  13.124 -                        w.write("new String[] {\n");
  13.125 -                        String sep = "";
  13.126 -                        for (String n : propsGetSet) {
  13.127 -                            w.write(sep);
  13.128 -                            if (n == null) {
  13.129 -                                w.write("    null");
  13.130 -                            } else {
  13.131 -                                w.write("    \"" + n + "\"");
  13.132 -                            }
  13.133 -                            sep = ",\n";
  13.134 -                        }
  13.135 -                        w.write("\n  });\n  return this;\n}\n");
  13.136 -                        
  13.137 -                        w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
  13.138 -                        w.write("  org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
  13.139 -                        w.write("}\n");
  13.140 -                    }
  13.141 -                    w.append("}\n");
  13.142 -                } finally {
  13.143 -                    w.close();
  13.144 -                }
  13.145 -            } catch (IOException ex) {
  13.146 -                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "Can't create " + className + ".java", e);
  13.147 -                return false;
  13.148 +        boolean ok = true;
  13.149 +        for (Element e : roundEnv.getElementsAnnotatedWith(Model.class)) {
  13.150 +            if (!processModel(e)) {
  13.151 +                ok = false;
  13.152              }
  13.153          }
  13.154 -        return true;
  13.155 +        for (Element e : roundEnv.getElementsAnnotatedWith(Page.class)) {
  13.156 +            if (!processPage(e)) {
  13.157 +                ok = false;
  13.158 +            }
  13.159 +        }
  13.160 +        if (roundEnv.processingOver()) {
  13.161 +            models.clear();
  13.162 +            for (Map.Entry<Element, Prprt[]> entry : verify.entrySet()) {
  13.163 +                TypeElement te = (TypeElement)entry.getKey();
  13.164 +                String fqn = processingEnv.getElementUtils().getBinaryName(te).toString();
  13.165 +                Element finalElem = processingEnv.getElementUtils().getTypeElement(fqn);
  13.166 +                if (finalElem == null) {
  13.167 +                    continue;
  13.168 +                }
  13.169 +                Prprt[] props;
  13.170 +                Model m = finalElem.getAnnotation(Model.class);
  13.171 +                if (m != null) {
  13.172 +                    props = Prprt.wrap(processingEnv, finalElem, m.properties());
  13.173 +                } else {
  13.174 +                    Page p = finalElem.getAnnotation(Page.class);
  13.175 +                    props = Prprt.wrap(processingEnv, finalElem, p.properties());
  13.176 +                }
  13.177 +                for (Prprt p : props) {
  13.178 +                    boolean[] isModel = { false };
  13.179 +                    boolean[] isEnum = { false };
  13.180 +                    boolean[] isPrimitive = { false };
  13.181 +                    String t = checkType(p, isModel, isEnum, isPrimitive);
  13.182 +                    if (isEnum[0]) {
  13.183 +                        continue;
  13.184 +                    }
  13.185 +                    if (isPrimitive[0]) {
  13.186 +                        continue;
  13.187 +                    }
  13.188 +                    if (isModel[0]) {
  13.189 +                        continue;
  13.190 +                    }
  13.191 +                    if ("java.lang.String".equals(t)) {
  13.192 +                        continue;
  13.193 +                    }
  13.194 +                    error("The type " + t + " should be defined by @Model annotation", entry.getKey());
  13.195 +                }
  13.196 +            }
  13.197 +            verify.clear();
  13.198 +        }
  13.199 +        return ok;
  13.200      }
  13.201  
  13.202      private InputStream openStream(String pkg, String name) throws IOException {
  13.203 @@ -157,6 +153,236 @@
  13.204          }
  13.205      }
  13.206  
  13.207 +    private void error(String msg, Element e) {
  13.208 +        processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, msg, e);
  13.209 +    }
  13.210 +    
  13.211 +    private boolean processModel(Element e) {
  13.212 +        boolean ok = true;
  13.213 +        Model m = e.getAnnotation(Model.class);
  13.214 +        if (m == null) {
  13.215 +            return true;
  13.216 +        }
  13.217 +        String pkg = findPkgName(e);
  13.218 +        Writer w;
  13.219 +        String className = m.className();
  13.220 +        models.put(e, className);
  13.221 +        try {
  13.222 +            StringWriter body = new StringWriter();
  13.223 +            List<String> propsGetSet = new ArrayList<>();
  13.224 +            List<String> functions = new ArrayList<>();
  13.225 +            Map<String, Collection<String>> propsDeps = new HashMap<>();
  13.226 +            Map<String, Collection<String>> functionDeps = new HashMap<>();
  13.227 +            Prprt[] props = createProps(e, m.properties());
  13.228 +            
  13.229 +            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
  13.230 +                ok = false;
  13.231 +            }
  13.232 +            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
  13.233 +                ok = false;
  13.234 +            }
  13.235 +            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
  13.236 +                ok = false;
  13.237 +            }
  13.238 +            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
  13.239 +                ok = false;
  13.240 +            }
  13.241 +            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
  13.242 +            w = new OutputStreamWriter(java.openOutputStream());
  13.243 +            try {
  13.244 +                w.append("package " + pkg + ";\n");
  13.245 +                w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
  13.246 +                w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
  13.247 +                w.append("import org.apidesign.bck2brwsr.core.JavaScriptOnly;\n");
  13.248 +                w.append("final class ").append(className).append(" implements Cloneable {\n");
  13.249 +                w.append("  private boolean locked;\n");
  13.250 +                w.append("  private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
  13.251 +                w.append(body.toString());
  13.252 +                w.append("  private static Class<" + inPckName(e) + "> modelFor() { return null; }\n");
  13.253 +                w.append("  public ").append(className).append("() {\n");
  13.254 +                w.append("    intKnckt();\n");
  13.255 +                w.append("  };\n");
  13.256 +                w.append("  private void intKnckt() {\n");
  13.257 +                w.append("    ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(this, ");
  13.258 +                writeStringArray(propsGetSet, w);
  13.259 +                w.append(", ");
  13.260 +                writeStringArray(functions, w);
  13.261 +                w.append("    );\n");
  13.262 +                w.append("  };\n");
  13.263 +                w.append("  ").append(className).append("(Object json) {\n");
  13.264 +                int values = 0;
  13.265 +                for (int i = 0; i < propsGetSet.size(); i += 4) {
  13.266 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
  13.267 +                    if (p == null) {
  13.268 +                        continue;
  13.269 +                    }
  13.270 +                    values++;
  13.271 +                }
  13.272 +                w.append("    Object[] ret = new Object[" + values + "];\n");
  13.273 +                w.append("    org.apidesign.bck2brwsr.htmlpage.ConvertTypes.extractJSON(json, new String[] {\n");
  13.274 +                for (int i = 0; i < propsGetSet.size(); i += 4) {
  13.275 +                    Prprt p = findPrprt(props, propsGetSet.get(i));
  13.276 +                    if (p == null) {
  13.277 +                        continue;
  13.278 +                    }
  13.279 +                    w.append("      \"").append(propsGetSet.get(i)).append("\",\n");
  13.280 +                }
  13.281 +                w.append("    }, ret);\n");
  13.282 +                for (int i = 0, cnt = 0, prop = 0; i < propsGetSet.size(); i += 4) {
  13.283 +                    final String pn = propsGetSet.get(i);
  13.284 +                    Prprt p = findPrprt(props, pn);
  13.285 +                    if (p == null) {
  13.286 +                        continue;
  13.287 +                    }
  13.288 +                    boolean[] isModel = { false };
  13.289 +                    boolean[] isEnum = { false };
  13.290 +                    boolean isPrimitive[] = { false };
  13.291 +                    String type = checkType(props[prop++], isModel, isEnum, isPrimitive);
  13.292 +                    if (p.array()) {
  13.293 +                        w.append("if (ret[" + cnt + "] instanceof Object[]) {\n");
  13.294 +                        w.append("  for (Object e : ((Object[])ret[" + cnt + "])) {\n");
  13.295 +                        if (isModel[0]) {
  13.296 +                            w.append("    this.prop_").append(pn).append(".add(new ");
  13.297 +                            w.append(type).append("(e));\n");
  13.298 +                        } else if (isEnum[0]) {
  13.299 +                            w.append("    this.prop_").append(pn);
  13.300 +                            w.append(".add(e == null ? null : ");
  13.301 +                            w.append(type).append(".valueOf((String)e));\n");
  13.302 +                        } else {
  13.303 +                            if (isPrimitive(type)) {
  13.304 +                                w.append("    this.prop_").append(pn).append(".add(((Number)e).");
  13.305 +                                w.append(type).append("Value());\n");
  13.306 +                            } else {
  13.307 +                                w.append("    this.prop_").append(pn).append(".add((");
  13.308 +                                w.append(type).append(")e);\n");
  13.309 +                            }
  13.310 +                        }
  13.311 +                        w.append("  }\n");
  13.312 +                        w.append("}\n");
  13.313 +                    } else {
  13.314 +                        if (isEnum[0]) {
  13.315 +                            w.append("    this.prop_").append(pn);
  13.316 +                            w.append(" = ret[" + cnt + "] == null ? null : ");
  13.317 +                            w.append(type).append(".valueOf((String)ret[" + cnt + "]);\n");
  13.318 +                        } else if (isPrimitive(type)) {
  13.319 +                            w.append("    this.prop_").append(pn);
  13.320 +                            w.append(" = ((Number)").append("ret[" + cnt + "]).");
  13.321 +                            w.append(type).append("Value();\n");
  13.322 +                        } else {
  13.323 +                            w.append("    this.prop_").append(pn);
  13.324 +                            w.append(" = (").append(type).append(')');
  13.325 +                            w.append("ret[" + cnt + "];\n");
  13.326 +                        }
  13.327 +                    }
  13.328 +                    cnt++;
  13.329 +                }
  13.330 +                w.append("    intKnckt();\n");
  13.331 +                w.append("  };\n");
  13.332 +                writeToString(props, w);
  13.333 +                writeClone(className, props, w);
  13.334 +                w.append("}\n");
  13.335 +            } finally {
  13.336 +                w.close();
  13.337 +            }
  13.338 +        } catch (IOException ex) {
  13.339 +            error("Can't create " + className + ".java", e);
  13.340 +            return false;
  13.341 +        }
  13.342 +        return ok;
  13.343 +    }
  13.344 +    
  13.345 +    private boolean processPage(Element e) {
  13.346 +        boolean ok = true;
  13.347 +        Page p = e.getAnnotation(Page.class);
  13.348 +        if (p == null) {
  13.349 +            return true;
  13.350 +        }
  13.351 +        String pkg = findPkgName(e);
  13.352 +
  13.353 +        ProcessPage pp;
  13.354 +        try (InputStream is = openStream(pkg, p.xhtml())) {
  13.355 +            pp = ProcessPage.readPage(is);
  13.356 +            is.close();
  13.357 +        } catch (IOException iOException) {
  13.358 +            error("Can't read " + p.xhtml() + " as " + iOException.getMessage(), e);
  13.359 +            ok = false;
  13.360 +            pp = null;
  13.361 +        }
  13.362 +        Writer w;
  13.363 +        String className = p.className();
  13.364 +        if (className.isEmpty()) {
  13.365 +            int indx = p.xhtml().indexOf('.');
  13.366 +            className = p.xhtml().substring(0, indx);
  13.367 +        }
  13.368 +        try {
  13.369 +            StringWriter body = new StringWriter();
  13.370 +            List<String> propsGetSet = new ArrayList<>();
  13.371 +            List<String> functions = new ArrayList<>();
  13.372 +            Map<String, Collection<String>> propsDeps = new HashMap<>();
  13.373 +            Map<String, Collection<String>> functionDeps = new HashMap<>();
  13.374 +            
  13.375 +            Prprt[] props = createProps(e, p.properties());
  13.376 +            if (!generateComputedProperties(body, props, e.getEnclosedElements(), propsGetSet, propsDeps)) {
  13.377 +                ok = false;
  13.378 +            }
  13.379 +            if (!generateOnChange(e, propsDeps, props, className, functionDeps)) {
  13.380 +                ok = false;
  13.381 +            }
  13.382 +            if (!generateProperties(e, body, props, propsGetSet, propsDeps, functionDeps)) {
  13.383 +                ok = false;
  13.384 +            }
  13.385 +            if (!generateFunctions(e, body, className, e.getEnclosedElements(), functions)) {
  13.386 +                ok = false;
  13.387 +            }
  13.388 +            if (!generateReceive(e, body, className, e.getEnclosedElements(), functions)) {
  13.389 +                ok = false;
  13.390 +            }
  13.391 +            
  13.392 +            FileObject java = processingEnv.getFiler().createSourceFile(pkg + '.' + className, e);
  13.393 +            w = new OutputStreamWriter(java.openOutputStream());
  13.394 +            try {
  13.395 +                w.append("package " + pkg + ";\n");
  13.396 +                w.append("import org.apidesign.bck2brwsr.htmlpage.api.*;\n");
  13.397 +                w.append("import org.apidesign.bck2brwsr.htmlpage.KOList;\n");
  13.398 +                w.append("final class ").append(className).append(" {\n");
  13.399 +                w.append("  private boolean locked;\n");
  13.400 +                if (!initializeOnClick(className, (TypeElement) e, w, pp)) {
  13.401 +                    ok = false;
  13.402 +                } else {
  13.403 +                    if (pp != null) for (String id : pp.ids()) {
  13.404 +                        String tag = pp.tagNameForId(id);
  13.405 +                        String type = type(tag);
  13.406 +                        w.append("  ").append("public final ").
  13.407 +                            append(type).append(' ').append(cnstnt(id)).append(" = new ").
  13.408 +                            append(type).append("(\"").append(id).append("\");\n");
  13.409 +                    }
  13.410 +                }
  13.411 +                w.append("  private org.apidesign.bck2brwsr.htmlpage.Knockout ko;\n");
  13.412 +                w.append(body.toString());
  13.413 +                if (!propsGetSet.isEmpty()) {
  13.414 +                    w.write("public " + className + " applyBindings() {\n");
  13.415 +                    w.write("  ko = org.apidesign.bck2brwsr.htmlpage.Knockout.applyBindings(");
  13.416 +                    w.write(className + ".class, this, ");
  13.417 +                    writeStringArray(propsGetSet, w);
  13.418 +                    w.append(", ");
  13.419 +                    writeStringArray(functions, w);
  13.420 +                    w.write(");\n  return this;\n}\n");
  13.421 +
  13.422 +                    w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
  13.423 +                    w.write("  org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
  13.424 +                    w.write("}\n");
  13.425 +                }
  13.426 +                w.append("}\n");
  13.427 +            } finally {
  13.428 +                w.close();
  13.429 +            }
  13.430 +        } catch (IOException ex) {
  13.431 +            error("Can't create " + className + ".java", e);
  13.432 +            return false;
  13.433 +        }
  13.434 +        return ok;
  13.435 +    }
  13.436 +
  13.437      private static String type(String tag) {
  13.438          if (tag.equals("title")) {
  13.439              return "Title";
  13.440 @@ -177,12 +403,13 @@
  13.441      }
  13.442  
  13.443      private static String cnstnt(String id) {
  13.444 -        return id.toUpperCase(Locale.ENGLISH).replace('.', '_').replace('-', '_');
  13.445 +        return id.replace('.', '_').replace('-', '_');
  13.446      }
  13.447  
  13.448      private boolean initializeOnClick(
  13.449          String className, TypeElement type, Writer w, ProcessPage pp
  13.450      ) throws IOException {
  13.451 +        boolean ok = true;
  13.452          TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
  13.453          { //for (Element clazz : pe.getEnclosedElements()) {
  13.454            //  if (clazz.getKind() != ElementKind.CLASS) {
  13.455 @@ -195,46 +422,27 @@
  13.456                  On oc = method.getAnnotation(On.class);
  13.457                  if (oc != null) {
  13.458                      for (String id : oc.id()) {
  13.459 +                        if (pp == null) {
  13.460 +                            error("id = " + id + " not found in HTML page.", method);
  13.461 +                            ok = false;
  13.462 +                            continue;
  13.463 +                        }
  13.464                          if (pp.tagNameForId(id) == null) {
  13.465 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
  13.466 -                            return false;
  13.467 +                            error("id = " + id + " does not exist in the HTML page. Found only " + pp.ids(), method);
  13.468 +                            ok = false;
  13.469 +                            continue;
  13.470                          }
  13.471                          ExecutableElement ee = (ExecutableElement)method;
  13.472 -                        StringBuilder params = new StringBuilder();
  13.473 -                        {
  13.474 -                            boolean first = true;
  13.475 -                            for (VariableElement ve : ee.getParameters()) {
  13.476 -                                if (!first) {
  13.477 -                                    params.append(", ");
  13.478 -                                }
  13.479 -                                first = false;
  13.480 -                                if (ve.asType() == stringType) {
  13.481 -                                    params.append('"').append(id).append('"');
  13.482 -                                    continue;
  13.483 -                                }
  13.484 -                                String rn = ve.asType().toString();
  13.485 -                                int last = rn.lastIndexOf('.');
  13.486 -                                if (last >= 0) {
  13.487 -                                    rn = rn.substring(last + 1);
  13.488 -                                }
  13.489 -                                if (rn.equals(className)) {
  13.490 -                                    params.append(className).append(".this");
  13.491 -                                    continue;
  13.492 -                                }
  13.493 -                                processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, 
  13.494 -                                    "@On method can only accept String or " + className + " arguments",
  13.495 -                                    ee
  13.496 -                                );
  13.497 -                                return false;
  13.498 -                            }
  13.499 -                        }
  13.500 +                        CharSequence params = wrapParams(ee, id, className, "ev", null);
  13.501                          if (!ee.getModifiers().contains(Modifier.STATIC)) {
  13.502 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method has to be static", ee);
  13.503 -                            return false;
  13.504 +                            error("@On method has to be static", ee);
  13.505 +                            ok = false;
  13.506 +                            continue;
  13.507                          }
  13.508                          if (ee.getModifiers().contains(Modifier.PRIVATE)) {
  13.509 -                            processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR, "@On method can't be private", ee);
  13.510 -                            return false;
  13.511 +                            error("@On method can't be private", ee);
  13.512 +                            ok = false;
  13.513 +                            continue;
  13.514                          }
  13.515                          w.append("  OnEvent." + oc.event()).append(".of(").append(cnstnt(id)).
  13.516                              append(").perform(new OnDispatch(" + dispatchCnt + "));\n");
  13.517 @@ -252,10 +460,10 @@
  13.518              }
  13.519              w.append("  }\n");
  13.520              if (dispatchCnt > 0) {
  13.521 -                w.append("class OnDispatch implements Runnable {\n");
  13.522 +                w.append("class OnDispatch implements OnHandler {\n");
  13.523                  w.append("  private final int dispatch;\n");
  13.524                  w.append("  OnDispatch(int d) { dispatch = d; }\n");
  13.525 -                w.append("  public void run() {\n");
  13.526 +                w.append("  public void onEvent(Object ev) {\n");
  13.527                  w.append("    switch (dispatch) {\n");
  13.528                  w.append(dispatch);
  13.529                  w.append("    }\n");
  13.530 @@ -265,7 +473,7 @@
  13.531              
  13.532  
  13.533          }
  13.534 -        return true;
  13.535 +        return ok;
  13.536      }
  13.537  
  13.538      @Override
  13.539 @@ -279,8 +487,7 @@
  13.540          
  13.541          Element cls = findClass(element);
  13.542          Page p = cls.getAnnotation(Page.class);
  13.543 -        PackageElement pe = (PackageElement) cls.getEnclosingElement();
  13.544 -        String pkg = pe.getQualifiedName().toString();
  13.545 +        String pkg = findPkgName(cls);
  13.546          ProcessPage pp;
  13.547          try {
  13.548              InputStream is = openStream(pkg, p.xhtml());
  13.549 @@ -290,7 +497,7 @@
  13.550              return Collections.emptyList();
  13.551          }
  13.552          
  13.553 -        List<Completion> cc = new ArrayList<Completion>();
  13.554 +        List<Completion> cc = new ArrayList<>();
  13.555          userText = userText.substring(1);
  13.556          for (String id : pp.ids()) {
  13.557              if (id.startsWith(userText)) {
  13.558 @@ -311,44 +518,89 @@
  13.559          return e.getEnclosingElement();
  13.560      }
  13.561  
  13.562 -    private static void generateProperties(
  13.563 -        Writer w, Property[] properties, Collection<String> props,
  13.564 -        Map<String,Collection<String>> deps
  13.565 +    private boolean generateProperties(
  13.566 +        Element where,
  13.567 +        Writer w, Prprt[] properties,
  13.568 +        Collection<String> props, 
  13.569 +        Map<String,Collection<String>> deps,
  13.570 +        Map<String,Collection<String>> functionDeps
  13.571      ) throws IOException {
  13.572 -        for (Property p : properties) {
  13.573 -            final String tn = typeName(p);
  13.574 -            String[] gs = toGetSet(p.name(), tn);
  13.575 +        boolean ok = true;
  13.576 +        for (Prprt p : properties) {
  13.577 +            final String tn;
  13.578 +            tn = typeName(where, p);
  13.579 +            String[] gs = toGetSet(p.name(), tn, p.array());
  13.580  
  13.581 -            w.write("private " + tn + " prop_" + p.name() + ";\n");
  13.582 -            w.write("public " + tn + " " + gs[0] + "() {\n");
  13.583 -            w.write("  if (locked) throw new IllegalStateException();\n");
  13.584 -            w.write("  return prop_" + p.name() + ";\n");
  13.585 -            w.write("}\n");
  13.586 -            w.write("public void " + gs[1] + "(" + tn + " v) {\n");
  13.587 -            w.write("  if (locked) throw new IllegalStateException();\n");
  13.588 -            w.write("  prop_" + p.name() + " = v;\n");
  13.589 -            w.write("  if (ko != null) {\n");
  13.590 -            w.write("    ko.valueHasMutated(\"" + p.name() + "\");\n");
  13.591 -            final Collection<String> dependants = deps.get(p.name());
  13.592 -            if (dependants != null) {
  13.593 -                for (String depProp : dependants) {
  13.594 -                    w.write("    ko.valueHasMutated(\"" + depProp + "\");\n");
  13.595 +            if (p.array()) {
  13.596 +                w.write("private KOList<" + tn + "> prop_" + p.name() + " = new KOList<" + tn + ">(\""
  13.597 +                    + p.name() + "\"");
  13.598 +                Collection<String> dependants = deps.get(p.name());
  13.599 +                if (dependants != null) {
  13.600 +                    for (String depProp : dependants) {
  13.601 +                        w.write(", ");
  13.602 +                        w.write('\"');
  13.603 +                        w.write(depProp);
  13.604 +                        w.write('\"');
  13.605 +                    }
  13.606                  }
  13.607 +                w.write(")");
  13.608 +                
  13.609 +                dependants = functionDeps.get(p.name());
  13.610 +                if (dependants != null) {
  13.611 +                    w.write(".onChange(new Runnable() { public void run() {\n");
  13.612 +                    for (String call : dependants) {
  13.613 +                        w.append(call);
  13.614 +                    }
  13.615 +                    w.write("}})");
  13.616 +                }
  13.617 +                w.write(";\n");
  13.618 +                
  13.619 +                w.write("public java.util.List<" + tn + "> " + gs[0] + "() {\n");
  13.620 +                w.write("  if (locked) throw new IllegalStateException();\n");
  13.621 +                w.write("  prop_" + p.name() + ".assign(ko);\n");
  13.622 +                w.write("  return prop_" + p.name() + ";\n");
  13.623 +                w.write("}\n");
  13.624 +            } else {
  13.625 +                w.write("private " + tn + " prop_" + p.name() + ";\n");
  13.626 +                w.write("public " + tn + " " + gs[0] + "() {\n");
  13.627 +                w.write("  if (locked) throw new IllegalStateException();\n");
  13.628 +                w.write("  return prop_" + p.name() + ";\n");
  13.629 +                w.write("}\n");
  13.630 +                w.write("public void " + gs[1] + "(" + tn + " v) {\n");
  13.631 +                w.write("  if (locked) throw new IllegalStateException();\n");
  13.632 +                w.write("  prop_" + p.name() + " = v;\n");
  13.633 +                w.write("  if (ko != null) {\n");
  13.634 +                w.write("    ko.valueHasMutated(\"" + p.name() + "\");\n");
  13.635 +                Collection<String> dependants = deps.get(p.name());
  13.636 +                if (dependants != null) {
  13.637 +                    for (String depProp : dependants) {
  13.638 +                        w.write("    ko.valueHasMutated(\"" + depProp + "\");\n");
  13.639 +                    }
  13.640 +                }
  13.641 +                w.write("  }\n");
  13.642 +                dependants = functionDeps.get(p.name());
  13.643 +                if (dependants != null) {
  13.644 +                    for (String call : dependants) {
  13.645 +                        w.append(call);
  13.646 +                    }
  13.647 +                }
  13.648 +                w.write("}\n");
  13.649              }
  13.650 -            w.write("  }\n");
  13.651 -            w.write("}\n");
  13.652              
  13.653              props.add(p.name());
  13.654              props.add(gs[2]);
  13.655              props.add(gs[3]);
  13.656              props.add(gs[0]);
  13.657          }
  13.658 +        return ok;
  13.659      }
  13.660  
  13.661      private boolean generateComputedProperties(
  13.662 -        Writer w, Collection<? extends Element> arr, Collection<String> props,
  13.663 +        Writer w, Prprt[] fixedProps,
  13.664 +        Collection<? extends Element> arr, Collection<String> props,
  13.665          Map<String,Collection<String>> deps
  13.666      ) throws IOException {
  13.667 +        boolean ok = true;
  13.668          for (Element e : arr) {
  13.669              if (e.getKind() != ElementKind.METHOD) {
  13.670                  continue;
  13.671 @@ -357,30 +609,43 @@
  13.672                  continue;
  13.673              }
  13.674              ExecutableElement ee = (ExecutableElement)e;
  13.675 -            final String tn = ee.getReturnType().toString();
  13.676 +            final TypeMirror rt = ee.getReturnType();
  13.677 +            final Types tu = processingEnv.getTypeUtils();
  13.678 +            TypeMirror ert = tu.erasure(rt);
  13.679 +            String tn = fqn(ert, ee);
  13.680 +            boolean array = false;
  13.681 +            if (tn.equals("java.util.List")) {
  13.682 +                array = true;
  13.683 +            }
  13.684 +            
  13.685              final String sn = ee.getSimpleName().toString();
  13.686 -            String[] gs = toGetSet(sn, tn);
  13.687 +            String[] gs = toGetSet(sn, tn, array);
  13.688              
  13.689              w.write("public " + tn + " " + gs[0] + "() {\n");
  13.690              w.write("  if (locked) throw new IllegalStateException();\n");
  13.691              int arg = 0;
  13.692              for (VariableElement pe : ee.getParameters()) {
  13.693                  final String dn = pe.getSimpleName().toString();
  13.694 -                final String dt = pe.asType().toString();
  13.695 -                String[] call = toGetSet(dn, dt);
  13.696 +                
  13.697 +                if (!verifyPropName(pe, dn, fixedProps)) {
  13.698 +                    ok = false;
  13.699 +                }
  13.700 +                
  13.701 +                final String dt = fqn(pe.asType(), ee);
  13.702 +                String[] call = toGetSet(dn, dt, false);
  13.703                  w.write("  " + dt + " arg" + (++arg) + " = ");
  13.704                  w.write(call[0] + "();\n");
  13.705                  
  13.706                  Collection<String> depends = deps.get(dn);
  13.707                  if (depends == null) {
  13.708 -                    depends = new LinkedHashSet<String>();
  13.709 +                    depends = new LinkedHashSet<>();
  13.710                      deps.put(dn, depends);
  13.711                  }
  13.712                  depends.add(sn);
  13.713              }
  13.714              w.write("  try {\n");
  13.715              w.write("    locked = true;\n");
  13.716 -            w.write("    return " + e.getEnclosingElement().getSimpleName() + '.' + e.getSimpleName() + "(");
  13.717 +            w.write("    return " + fqn(ee.getEnclosingElement().asType(), ee) + '.' + e.getSimpleName() + "(");
  13.718              String sep = "";
  13.719              for (int i = 1; i <= arg; i++) {
  13.720                  w.write(sep);
  13.721 @@ -392,17 +657,17 @@
  13.722              w.write("    locked = false;\n");
  13.723              w.write("  }\n");
  13.724              w.write("}\n");
  13.725 -            
  13.726 +
  13.727              props.add(e.getSimpleName().toString());
  13.728              props.add(gs[2]);
  13.729              props.add(null);
  13.730              props.add(gs[0]);
  13.731          }
  13.732          
  13.733 -        return true;
  13.734 +        return ok;
  13.735      }
  13.736  
  13.737 -    private static String[] toGetSet(String name, String type) {
  13.738 +    private static String[] toGetSet(String name, String type, boolean array) {
  13.739          String n = Character.toUpperCase(name.charAt(0)) + name.substring(1);
  13.740          String bck2brwsrType = "L" + type.replace('.', '_') + "_2";
  13.741          if ("int".equals(type)) {
  13.742 @@ -417,6 +682,14 @@
  13.743              bck2brwsrType = "Z";
  13.744          }
  13.745          final String nu = n.replace('.', '_');
  13.746 +        if (array) {
  13.747 +            return new String[] { 
  13.748 +                "get" + n,
  13.749 +                null,
  13.750 +                "get" + nu + "__Ljava_util_List_2",
  13.751 +                null
  13.752 +            };
  13.753 +        }
  13.754          return new String[]{
  13.755              pref + n, 
  13.756              "set" + n, 
  13.757 @@ -425,11 +698,702 @@
  13.758          };
  13.759      }
  13.760  
  13.761 -    private static String typeName(Property p) {
  13.762 -        try {
  13.763 -            return p.type().getName();
  13.764 -        } catch (MirroredTypeException ex) {
  13.765 -            return ex.getTypeMirror().toString();
  13.766 +    private String typeName(Element where, Prprt p) {
  13.767 +        String ret;
  13.768 +        boolean[] isModel = { false };
  13.769 +        boolean[] isEnum = { false };
  13.770 +        boolean isPrimitive[] = { false };
  13.771 +        ret = checkType(p, isModel, isEnum, isPrimitive);
  13.772 +        if (p.array()) {
  13.773 +            String bt = findBoxedType(ret);
  13.774 +            if (bt != null) {
  13.775 +                return bt;
  13.776 +            }
  13.777 +        }
  13.778 +        return ret;
  13.779 +    }
  13.780 +    
  13.781 +    private static String findBoxedType(String ret) {
  13.782 +        if (ret.equals("boolean")) {
  13.783 +            return Boolean.class.getName();
  13.784 +        }
  13.785 +        if (ret.equals("byte")) {
  13.786 +            return Byte.class.getName();
  13.787 +        }
  13.788 +        if (ret.equals("short")) {
  13.789 +            return Short.class.getName();
  13.790 +        }
  13.791 +        if (ret.equals("char")) {
  13.792 +            return Character.class.getName();
  13.793 +        }
  13.794 +        if (ret.equals("int")) {
  13.795 +            return Integer.class.getName();
  13.796 +        }
  13.797 +        if (ret.equals("long")) {
  13.798 +            return Long.class.getName();
  13.799 +        }
  13.800 +        if (ret.equals("float")) {
  13.801 +            return Float.class.getName();
  13.802 +        }
  13.803 +        if (ret.equals("double")) {
  13.804 +            return Double.class.getName();
  13.805 +        }
  13.806 +        return null;
  13.807 +    }
  13.808 +
  13.809 +    private boolean verifyPropName(Element e, String propName, Prprt[] existingProps) {
  13.810 +        StringBuilder sb = new StringBuilder();
  13.811 +        String sep = "";
  13.812 +        for (Prprt Prprt : existingProps) {
  13.813 +            if (Prprt.name().equals(propName)) {
  13.814 +                return true;
  13.815 +            }
  13.816 +            sb.append(sep);
  13.817 +            sb.append('"');
  13.818 +            sb.append(Prprt.name());
  13.819 +            sb.append('"');
  13.820 +            sep = ", ";
  13.821 +        }
  13.822 +        error(
  13.823 +            propName + " is not one of known properties: " + sb
  13.824 +            , e
  13.825 +        );
  13.826 +        return false;
  13.827 +    }
  13.828 +
  13.829 +    private static String findPkgName(Element e) {
  13.830 +        for (;;) {
  13.831 +            if (e.getKind() == ElementKind.PACKAGE) {
  13.832 +                return ((PackageElement)e).getQualifiedName().toString();
  13.833 +            }
  13.834 +            e = e.getEnclosingElement();
  13.835          }
  13.836      }
  13.837 +
  13.838 +    private boolean generateFunctions(
  13.839 +        Element clazz, StringWriter body, String className, 
  13.840 +        List<? extends Element> enclosedElements, List<String> functions
  13.841 +    ) {
  13.842 +        for (Element m : enclosedElements) {
  13.843 +            if (m.getKind() != ElementKind.METHOD) {
  13.844 +                continue;
  13.845 +            }
  13.846 +            ExecutableElement e = (ExecutableElement)m;
  13.847 +            OnFunction onF = e.getAnnotation(OnFunction.class);
  13.848 +            if (onF == null) {
  13.849 +                continue;
  13.850 +            }
  13.851 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
  13.852 +                error("@OnFunction method needs to be static", e);
  13.853 +                return false;
  13.854 +            }
  13.855 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
  13.856 +                error("@OnFunction method cannot be private", e);
  13.857 +                return false;
  13.858 +            }
  13.859 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
  13.860 +                error("@OnFunction method should return void", e);
  13.861 +                return false;
  13.862 +            }
  13.863 +            String n = e.getSimpleName().toString();
  13.864 +            body.append("private void ").append(n).append("(Object data, Object ev) {\n");
  13.865 +            body.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
  13.866 +            body.append(wrapParams(e, null, className, "ev", "data"));
  13.867 +            body.append(");\n");
  13.868 +            body.append("}\n");
  13.869 +            
  13.870 +            functions.add(n);
  13.871 +            functions.add(n + "__VLjava_lang_Object_2Ljava_lang_Object_2");
  13.872 +        }
  13.873 +        return true;
  13.874 +    }
  13.875 +
  13.876 +    private boolean generateOnChange(Element clazz, Map<String,Collection<String>> propDeps,
  13.877 +        Prprt[] properties, String className, 
  13.878 +        Map<String, Collection<String>> functionDeps
  13.879 +    ) {
  13.880 +        for (Element m : clazz.getEnclosedElements()) {
  13.881 +            if (m.getKind() != ElementKind.METHOD) {
  13.882 +                continue;
  13.883 +            }
  13.884 +            ExecutableElement e = (ExecutableElement) m;
  13.885 +            OnPropertyChange onPC = e.getAnnotation(OnPropertyChange.class);
  13.886 +            if (onPC == null) {
  13.887 +                continue;
  13.888 +            }
  13.889 +            for (String pn : onPC.value()) {
  13.890 +                if (findPrprt(properties, pn) == null && findDerivedFrom(propDeps, pn).isEmpty()) {
  13.891 +                    error("No Prprt named '" + pn + "' in the model", clazz);
  13.892 +                    return false;
  13.893 +                }
  13.894 +            }
  13.895 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
  13.896 +                error("@OnPrprtChange method needs to be static", e);
  13.897 +                return false;
  13.898 +            }
  13.899 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
  13.900 +                error("@OnPrprtChange method cannot be private", e);
  13.901 +                return false;
  13.902 +            }
  13.903 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
  13.904 +                error("@OnPrprtChange method should return void", e);
  13.905 +                return false;
  13.906 +            }
  13.907 +            String n = e.getSimpleName().toString();
  13.908 +            
  13.909 +            
  13.910 +            for (String pn : onPC.value()) {
  13.911 +                StringBuilder call = new StringBuilder();
  13.912 +                call.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
  13.913 +                call.append(wrapPropName(e, className, "name", pn));
  13.914 +                call.append(");\n");
  13.915 +                
  13.916 +                Collection<String> change = functionDeps.get(pn);
  13.917 +                if (change == null) {
  13.918 +                    change = new ArrayList<>();
  13.919 +                    functionDeps.put(pn, change);
  13.920 +                }
  13.921 +                change.add(call.toString());
  13.922 +                for (String dpn : findDerivedFrom(propDeps, pn)) {
  13.923 +                    change = functionDeps.get(dpn);
  13.924 +                    if (change == null) {
  13.925 +                        change = new ArrayList<>();
  13.926 +                        functionDeps.put(dpn, change);
  13.927 +                    }
  13.928 +                    change.add(call.toString());
  13.929 +                }
  13.930 +            }
  13.931 +        }
  13.932 +        return true;
  13.933 +    }
  13.934 +    
  13.935 +    private boolean generateReceive(
  13.936 +        Element clazz, StringWriter body, String className, 
  13.937 +        List<? extends Element> enclosedElements, List<String> functions
  13.938 +    ) {
  13.939 +        for (Element m : enclosedElements) {
  13.940 +            if (m.getKind() != ElementKind.METHOD) {
  13.941 +                continue;
  13.942 +            }
  13.943 +            ExecutableElement e = (ExecutableElement)m;
  13.944 +            OnReceive onR = e.getAnnotation(OnReceive.class);
  13.945 +            if (onR == null) {
  13.946 +                continue;
  13.947 +            }
  13.948 +            if (!e.getModifiers().contains(Modifier.STATIC)) {
  13.949 +                error("@OnReceive method needs to be static", e);
  13.950 +                return false;
  13.951 +            }
  13.952 +            if (e.getModifiers().contains(Modifier.PRIVATE)) {
  13.953 +                error("@OnReceive method cannot be private", e);
  13.954 +                return false;
  13.955 +            }
  13.956 +            if (e.getReturnType().getKind() != TypeKind.VOID) {
  13.957 +                error("@OnReceive method should return void", e);
  13.958 +                return false;
  13.959 +            }
  13.960 +            String modelClass = null;
  13.961 +            boolean expectsList = false;
  13.962 +            List<String> args = new ArrayList<>();
  13.963 +            {
  13.964 +                for (VariableElement ve : e.getParameters()) {
  13.965 +                    TypeMirror modelType = null;
  13.966 +                    if (ve.asType().toString().equals(className)) {
  13.967 +                        args.add(className + ".this");
  13.968 +                    } else if (isModel(ve.asType())) {
  13.969 +                        modelType = ve.asType();
  13.970 +                    } else if (ve.asType().getKind() == TypeKind.ARRAY) {
  13.971 +                        modelType = ((ArrayType)ve.asType()).getComponentType();
  13.972 +                        expectsList = true;
  13.973 +                    }
  13.974 +                    if (modelType != null) {
  13.975 +                        if (modelClass != null) {
  13.976 +                            error("There can be only one model class among arguments", e);
  13.977 +                        } else {
  13.978 +                            modelClass = modelType.toString();
  13.979 +                            if (expectsList) {
  13.980 +                                args.add("arr");
  13.981 +                            } else {
  13.982 +                                args.add("arr[0]");
  13.983 +                            }
  13.984 +                        }
  13.985 +                    }
  13.986 +                }
  13.987 +            }
  13.988 +            if (modelClass == null) {
  13.989 +                error("The method needs to have one @Model class as parameter", e);
  13.990 +            }
  13.991 +            String n = e.getSimpleName().toString();
  13.992 +            body.append("public void ").append(n).append("(");
  13.993 +            StringBuilder assembleURL = new StringBuilder();
  13.994 +            String jsonpVarName = null;
  13.995 +            {
  13.996 +                String sep = "";
  13.997 +                boolean skipJSONP = onR.jsonp().isEmpty();
  13.998 +                for (String p : findParamNames(e, onR.url(), assembleURL)) {
  13.999 +                    if (!skipJSONP && p.equals(onR.jsonp())) {
 13.1000 +                        skipJSONP = true;
 13.1001 +                        jsonpVarName = p;
 13.1002 +                        continue;
 13.1003 +                    }
 13.1004 +                    body.append(sep);
 13.1005 +                    body.append("String ").append(p);
 13.1006 +                    sep = ", ";
 13.1007 +                }
 13.1008 +                if (!skipJSONP) {
 13.1009 +                    error(
 13.1010 +                        "Name of jsonp attribute ('" + onR.jsonp() + 
 13.1011 +                        "') is not used in url attribute '" + onR.url() + "'", e
 13.1012 +                    );
 13.1013 +                }
 13.1014 +            }
 13.1015 +            body.append(") {\n");
 13.1016 +            body.append("  final Object[] result = { null };\n");
 13.1017 +            body.append(
 13.1018 +                "  class ProcessResult implements Runnable {\n" +
 13.1019 +                "    @Override\n" +
 13.1020 +                "    public void run() {\n" +
 13.1021 +                "      Object value = result[0];\n");
 13.1022 +            body.append(
 13.1023 +                "      " + modelClass + "[] arr;\n");
 13.1024 +            body.append(
 13.1025 +                "      if (value instanceof Object[]) {\n" +
 13.1026 +                "        Object[] data = ((Object[])value);\n" +
 13.1027 +                "        arr = new " + modelClass + "[data.length];\n" +
 13.1028 +                "        for (int i = 0; i < data.length; i++) {\n" +
 13.1029 +                "          arr[i] = new " + modelClass + "(data[i]);\n" +
 13.1030 +                "        }\n" +
 13.1031 +                "      } else {\n" +
 13.1032 +                "        arr = new " + modelClass + "[1];\n" +
 13.1033 +                "        arr[0] = new " + modelClass + "(value);\n" +
 13.1034 +                "      }\n"
 13.1035 +            );
 13.1036 +            {
 13.1037 +                body.append(clazz.getSimpleName()).append(".").append(n).append("(");
 13.1038 +                String sep = "";
 13.1039 +                for (String arg : args) {
 13.1040 +                    body.append(sep);
 13.1041 +                    body.append(arg);
 13.1042 +                    sep = ", ";
 13.1043 +                }
 13.1044 +                body.append(");\n");
 13.1045 +            }
 13.1046 +            body.append(
 13.1047 +                "    }\n" +
 13.1048 +                "  }\n"
 13.1049 +            );
 13.1050 +            body.append("  ProcessResult pr = new ProcessResult();\n");
 13.1051 +            if (jsonpVarName != null) {
 13.1052 +                body.append("  String ").append(jsonpVarName).
 13.1053 +                    append(" = org.apidesign.bck2brwsr.htmlpage.ConvertTypes.createJSONP(result, pr);\n");
 13.1054 +            }
 13.1055 +            body.append("  org.apidesign.bck2brwsr.htmlpage.ConvertTypes.loadJSON(\n      ");
 13.1056 +            body.append(assembleURL);
 13.1057 +            body.append(", result, pr, ").append(jsonpVarName).append("\n  );\n");
 13.1058 +//            body.append("  ").append(clazz.getSimpleName()).append(".").append(n).append("(");
 13.1059 +//            body.append(wrapParams(e, null, className, "ev", "data"));
 13.1060 +//            body.append(");\n");
 13.1061 +            body.append("}\n");
 13.1062 +        }
 13.1063 +        return true;
 13.1064 +    }
 13.1065 +
 13.1066 +    private CharSequence wrapParams(
 13.1067 +        ExecutableElement ee, String id, String className, String evName, String dataName
 13.1068 +    ) {
 13.1069 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 13.1070 +        StringBuilder params = new StringBuilder();
 13.1071 +        boolean first = true;
 13.1072 +        for (VariableElement ve : ee.getParameters()) {
 13.1073 +            if (!first) {
 13.1074 +                params.append(", ");
 13.1075 +            }
 13.1076 +            first = false;
 13.1077 +            String toCall = null;
 13.1078 +            if (ve.asType() == stringType) {
 13.1079 +                if (ve.getSimpleName().contentEquals("id")) {
 13.1080 +                    params.append('"').append(id).append('"');
 13.1081 +                    continue;
 13.1082 +                }
 13.1083 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toString(";
 13.1084 +            }
 13.1085 +            if (ve.asType().getKind() == TypeKind.DOUBLE) {
 13.1086 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toDouble(";
 13.1087 +            }
 13.1088 +            if (ve.asType().getKind() == TypeKind.INT) {
 13.1089 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toInt(";
 13.1090 +            }
 13.1091 +            if (dataName != null && ve.getSimpleName().contentEquals(dataName) && isModel(ve.asType())) {
 13.1092 +                toCall = "org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toModel(" + ve.asType() + ".class, ";
 13.1093 +            }
 13.1094 +
 13.1095 +            if (toCall != null) {
 13.1096 +                params.append(toCall);
 13.1097 +                if (dataName != null && ve.getSimpleName().contentEquals(dataName)) {
 13.1098 +                    params.append(dataName);
 13.1099 +                    params.append(", null");
 13.1100 +                } else {
 13.1101 +                    if (evName == null) {
 13.1102 +                        final StringBuilder sb = new StringBuilder();
 13.1103 +                        sb.append("Unexpected string parameter name.");
 13.1104 +                        if (dataName != null) {
 13.1105 +                            sb.append(" Try \"").append(dataName).append("\"");
 13.1106 +                        }
 13.1107 +                        error(sb.toString(), ee);
 13.1108 +                    }
 13.1109 +                    params.append(evName);
 13.1110 +                    params.append(", \"");
 13.1111 +                    params.append(ve.getSimpleName().toString());
 13.1112 +                    params.append("\"");
 13.1113 +                }
 13.1114 +                params.append(")");
 13.1115 +                continue;
 13.1116 +            }
 13.1117 +            String rn = fqn(ve.asType(), ee);
 13.1118 +            int last = rn.lastIndexOf('.');
 13.1119 +            if (last >= 0) {
 13.1120 +                rn = rn.substring(last + 1);
 13.1121 +            }
 13.1122 +            if (rn.equals(className)) {
 13.1123 +                params.append(className).append(".this");
 13.1124 +                continue;
 13.1125 +            }
 13.1126 +            error(
 13.1127 +                "@On method can only accept String named 'id' or " + className + " arguments",
 13.1128 +                ee
 13.1129 +            );
 13.1130 +        }
 13.1131 +        return params;
 13.1132 +    }
 13.1133 +    
 13.1134 +    
 13.1135 +    private CharSequence wrapPropName(
 13.1136 +        ExecutableElement ee, String className, String propName, String propValue
 13.1137 +    ) {
 13.1138 +        TypeMirror stringType = processingEnv.getElementUtils().getTypeElement("java.lang.String").asType();
 13.1139 +        StringBuilder params = new StringBuilder();
 13.1140 +        boolean first = true;
 13.1141 +        for (VariableElement ve : ee.getParameters()) {
 13.1142 +            if (!first) {
 13.1143 +                params.append(", ");
 13.1144 +            }
 13.1145 +            first = false;
 13.1146 +            if (ve.asType() == stringType) {
 13.1147 +                if (propName != null && ve.getSimpleName().contentEquals(propName)) {
 13.1148 +                    params.append('"').append(propValue).append('"');
 13.1149 +                } else {
 13.1150 +                    error("Unexpected string parameter name. Try \"" + propName + "\".", ee);
 13.1151 +                }
 13.1152 +                continue;
 13.1153 +            }
 13.1154 +            String rn = fqn(ve.asType(), ee);
 13.1155 +            int last = rn.lastIndexOf('.');
 13.1156 +            if (last >= 0) {
 13.1157 +                rn = rn.substring(last + 1);
 13.1158 +            }
 13.1159 +            if (rn.equals(className)) {
 13.1160 +                params.append(className).append(".this");
 13.1161 +                continue;
 13.1162 +            }
 13.1163 +            error(
 13.1164 +                "@OnPrprtChange method can only accept String or " + className + " arguments",
 13.1165 +                ee);
 13.1166 +        }
 13.1167 +        return params;
 13.1168 +    }
 13.1169 +    
 13.1170 +    private boolean isModel(TypeMirror tm) {
 13.1171 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
 13.1172 +        if (e == null) {
 13.1173 +            return false;
 13.1174 +        }
 13.1175 +        for (Element ch : e.getEnclosedElements()) {
 13.1176 +            if (ch.getKind() == ElementKind.METHOD) {
 13.1177 +                ExecutableElement ee = (ExecutableElement)ch;
 13.1178 +                if (ee.getParameters().isEmpty() && ee.getSimpleName().contentEquals("modelFor")) {
 13.1179 +                    return true;
 13.1180 +                }
 13.1181 +            }
 13.1182 +        }
 13.1183 +        return models.values().contains(e.getSimpleName().toString());
 13.1184 +    }
 13.1185 +
 13.1186 +    private void writeStringArray(List<String> strings, Writer w) throws IOException {
 13.1187 +        w.write("new String[] {\n");
 13.1188 +        String sep = "";
 13.1189 +        for (String n : strings) {
 13.1190 +            w.write(sep);
 13.1191 +            if (n == null) {
 13.1192 +                w.write("    null");
 13.1193 +            } else {
 13.1194 +                w.write("    \"" + n + "\"");
 13.1195 +            }
 13.1196 +            sep = ",\n";
 13.1197 +        }
 13.1198 +        w.write("\n  }");
 13.1199 +    }
 13.1200 +    
 13.1201 +    private void writeToString(Prprt[] props, Writer w) throws IOException {
 13.1202 +        w.write("  public String toString() {\n");
 13.1203 +        w.write("    StringBuilder sb = new StringBuilder();\n");
 13.1204 +        w.write("    sb.append('{');\n");
 13.1205 +        String sep = "";
 13.1206 +        for (Prprt p : props) {
 13.1207 +            w.write(sep);
 13.1208 +            w.append("    sb.append('\"').append(\"" + p.name() + "\")");
 13.1209 +                w.append(".append('\"').append(\":\");\n");
 13.1210 +            w.append("    sb.append(org.apidesign.bck2brwsr.htmlpage.ConvertTypes.toJSON(prop_");
 13.1211 +            w.append(p.name()).append("));\n");
 13.1212 +            sep =    "    sb.append(',');\n";
 13.1213 +        }
 13.1214 +        w.write("    sb.append('}');\n");
 13.1215 +        w.write("    return sb.toString();\n");
 13.1216 +        w.write("  }\n");
 13.1217 +    }
 13.1218 +    private void writeClone(String className, Prprt[] props, Writer w) throws IOException {
 13.1219 +        w.write("  public " + className + " clone() {\n");
 13.1220 +        w.write("    " + className + " ret = new " + className + "();\n");
 13.1221 +        for (Prprt p : props) {
 13.1222 +            if (!p.array()) {
 13.1223 +                boolean isModel[] = { false };
 13.1224 +                boolean isEnum[] = { false };
 13.1225 +                boolean isPrimitive[] = { false };
 13.1226 +                checkType(p, isModel, isEnum, isPrimitive);
 13.1227 +                if (!isModel[0]) {
 13.1228 +                    w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ";\n");
 13.1229 +                    continue;
 13.1230 +                }
 13.1231 +                w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
 13.1232 +            } else {
 13.1233 +                w.write("    ret.prop_" + p.name() + " = prop_" + p.name() + ".clone();\n");
 13.1234 +            }
 13.1235 +        }
 13.1236 +        
 13.1237 +        w.write("    return ret;\n");
 13.1238 +        w.write("  }\n");
 13.1239 +    }
 13.1240 +
 13.1241 +    private String inPckName(Element e) {
 13.1242 +        StringBuilder sb = new StringBuilder();
 13.1243 +        while (e.getKind() != ElementKind.PACKAGE) {
 13.1244 +            if (sb.length() == 0) {
 13.1245 +                sb.append(e.getSimpleName());
 13.1246 +            } else {
 13.1247 +                sb.insert(0, '.');
 13.1248 +                sb.insert(0, e.getSimpleName());
 13.1249 +            }
 13.1250 +            e = e.getEnclosingElement();
 13.1251 +        }
 13.1252 +        return sb.toString();
 13.1253 +    }
 13.1254 +
 13.1255 +    private String fqn(TypeMirror pt, Element relative) {
 13.1256 +        if (pt.getKind() == TypeKind.ERROR) {
 13.1257 +            final Elements eu = processingEnv.getElementUtils();
 13.1258 +            PackageElement pckg = eu.getPackageOf(relative);
 13.1259 +            return pckg.getQualifiedName() + "." + pt.toString();
 13.1260 +        }
 13.1261 +        return pt.toString();
 13.1262 +    }
 13.1263 +
 13.1264 +    private String checkType(Prprt p, boolean[] isModel, boolean[] isEnum, boolean[] isPrimitive) {
 13.1265 +        TypeMirror tm;
 13.1266 +        try {
 13.1267 +            String ret = p.typeName(processingEnv);
 13.1268 +            TypeElement e = processingEnv.getElementUtils().getTypeElement(ret);
 13.1269 +            if (e == null) {
 13.1270 +                isModel[0] = true;
 13.1271 +                isEnum[0] = false;
 13.1272 +                isPrimitive[0] = false;
 13.1273 +                return ret;
 13.1274 +            }
 13.1275 +            tm = e.asType();
 13.1276 +        } catch (MirroredTypeException ex) {
 13.1277 +            tm = ex.getTypeMirror();
 13.1278 +        }
 13.1279 +        tm = processingEnv.getTypeUtils().erasure(tm);
 13.1280 +        isPrimitive[0] = tm.getKind().isPrimitive();
 13.1281 +        final Element e = processingEnv.getTypeUtils().asElement(tm);
 13.1282 +        final Model m = e == null ? null : e.getAnnotation(Model.class);
 13.1283 +        
 13.1284 +        String ret;
 13.1285 +        if (m != null) {
 13.1286 +            ret = findPkgName(e) + '.' + m.className();
 13.1287 +            isModel[0] = true;
 13.1288 +            models.put(e, m.className());
 13.1289 +        } else if (findModelForMthd(e)) {
 13.1290 +            ret = ((TypeElement)e).getQualifiedName().toString();
 13.1291 +            isModel[0] = true;
 13.1292 +        } else {
 13.1293 +            ret = tm.toString();
 13.1294 +        }
 13.1295 +        TypeMirror enm = processingEnv.getElementUtils().getTypeElement("java.lang.Enum").asType();
 13.1296 +        enm = processingEnv.getTypeUtils().erasure(enm);
 13.1297 +        isEnum[0] = processingEnv.getTypeUtils().isSubtype(tm, enm);
 13.1298 +        return ret;
 13.1299 +    }
 13.1300 +    
 13.1301 +    private static boolean findModelForMthd(Element clazz) {
 13.1302 +        if (clazz == null) {
 13.1303 +            return false;
 13.1304 +        }
 13.1305 +        for (Element e : clazz.getEnclosedElements()) {
 13.1306 +            if (e.getKind() == ElementKind.METHOD) {
 13.1307 +                ExecutableElement ee = (ExecutableElement)e;
 13.1308 +                if (
 13.1309 +                    ee.getSimpleName().contentEquals("modelFor") &&
 13.1310 +                    ee.getParameters().isEmpty()
 13.1311 +                ) {
 13.1312 +                    return true;
 13.1313 +                }
 13.1314 +            }
 13.1315 +        }
 13.1316 +        return false;
 13.1317 +    }
 13.1318 +
 13.1319 +    private Iterable<String> findParamNames(Element e, String url, StringBuilder assembleURL) {
 13.1320 +        List<String> params = new ArrayList<>();
 13.1321 +
 13.1322 +        for (int pos = 0; ;) {
 13.1323 +            int next = url.indexOf('{', pos);
 13.1324 +            if (next == -1) {
 13.1325 +                assembleURL.append('"')
 13.1326 +                    .append(url.substring(pos))
 13.1327 +                    .append('"');
 13.1328 +                return params;
 13.1329 +            }
 13.1330 +            int close = url.indexOf('}', next);
 13.1331 +            if (close == -1) {
 13.1332 +                error("Unbalanced '{' and '}' in " + url, e);
 13.1333 +                return params;
 13.1334 +            }
 13.1335 +            final String paramName = url.substring(next + 1, close);
 13.1336 +            params.add(paramName);
 13.1337 +            assembleURL.append('"')
 13.1338 +                .append(url.substring(pos, next))
 13.1339 +                .append("\" + ").append(paramName).append(" + ");
 13.1340 +            pos = close + 1;
 13.1341 +        }
 13.1342 +    }
 13.1343 +
 13.1344 +    private static Prprt findPrprt(Prprt[] properties, String propName) {
 13.1345 +        for (Prprt p : properties) {
 13.1346 +            if (propName.equals(p.name())) {
 13.1347 +                return p;
 13.1348 +            }
 13.1349 +        }
 13.1350 +        return null;
 13.1351 +    }
 13.1352 +
 13.1353 +    private boolean isPrimitive(String type) {
 13.1354 +        return 
 13.1355 +            "int".equals(type) ||
 13.1356 +            "double".equals(type) ||
 13.1357 +            "long".equals(type) ||
 13.1358 +            "short".equals(type) ||
 13.1359 +            "byte".equals(type) ||
 13.1360 +            "float".equals(type);
 13.1361 +    }
 13.1362 +
 13.1363 +    private static Collection<String> findDerivedFrom(Map<String, Collection<String>> propsDeps, String derivedProp) {
 13.1364 +        Set<String> names = new HashSet<>();
 13.1365 +        for (Map.Entry<String, Collection<String>> e : propsDeps.entrySet()) {
 13.1366 +            if (e.getValue().contains(derivedProp)) {
 13.1367 +                names.add(e.getKey());
 13.1368 +            }
 13.1369 +        }
 13.1370 +        return names;
 13.1371 +    }
 13.1372 +    
 13.1373 +    private Prprt[] createProps(Element e, Property[] arr) {
 13.1374 +        Prprt[] ret = Prprt.wrap(processingEnv, e, arr);
 13.1375 +        Prprt[] prev = verify.put(e, ret);
 13.1376 +        if (prev != null) {
 13.1377 +            error("Two sets of properties for ", e);
 13.1378 +        }
 13.1379 +        return ret;
 13.1380 +    }
 13.1381 +    
 13.1382 +    private static class Prprt {
 13.1383 +        private final Element e;
 13.1384 +        private final AnnotationMirror tm;
 13.1385 +        private final Property p;
 13.1386 +
 13.1387 +        public Prprt(Element e, AnnotationMirror tm, Property p) {
 13.1388 +            this.e = e;
 13.1389 +            this.tm = tm;
 13.1390 +            this.p = p;
 13.1391 +        }
 13.1392 +        
 13.1393 +        String name() {
 13.1394 +            return p.name();
 13.1395 +        }
 13.1396 +        
 13.1397 +        boolean array() {
 13.1398 +            return p.array();
 13.1399 +        }
 13.1400 +
 13.1401 +        String typeName(ProcessingEnvironment env) {
 13.1402 +            try {
 13.1403 +                return p.type().getName();
 13.1404 +            } catch (IncompleteAnnotationException | AnnotationTypeMismatchException ex) {
 13.1405 +                for (Object v : getAnnoValues(env)) {
 13.1406 +                    String s = v.toString().replace(" ", "");
 13.1407 +                    if (s.startsWith("type=") && s.endsWith(".class")) {
 13.1408 +                        return s.substring(5, s.length() - 6);
 13.1409 +                    }
 13.1410 +                }
 13.1411 +                throw ex;
 13.1412 +            }
 13.1413 +        }
 13.1414 +        
 13.1415 +        
 13.1416 +        static Prprt[] wrap(ProcessingEnvironment pe, Element e, Property[] arr) {
 13.1417 +            if (arr.length == 0) {
 13.1418 +                return new Prprt[0];
 13.1419 +            }
 13.1420 +            
 13.1421 +            if (e.getKind() != ElementKind.CLASS) {
 13.1422 +                throw new IllegalStateException("" + e.getKind());
 13.1423 +            }
 13.1424 +            TypeElement te = (TypeElement)e;
 13.1425 +            List<? extends AnnotationValue> val = null;
 13.1426 +            for (AnnotationMirror an : te.getAnnotationMirrors()) {
 13.1427 +                for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : an.getElementValues().entrySet()) {
 13.1428 +                    if (entry.getKey().getSimpleName().contentEquals("properties")) {
 13.1429 +                        val = (List)entry.getValue().getValue();
 13.1430 +                        break;
 13.1431 +                    }
 13.1432 +                }
 13.1433 +            }
 13.1434 +            if (val == null || val.size() != arr.length) {
 13.1435 +                pe.getMessager().printMessage(Diagnostic.Kind.ERROR, "" + val, e);
 13.1436 +                return new Prprt[0];
 13.1437 +            }
 13.1438 +            Prprt[] ret = new Prprt[arr.length];
 13.1439 +            BIG: for (int i = 0; i < ret.length; i++) {
 13.1440 +                AnnotationMirror am = (AnnotationMirror)val.get(i).getValue();
 13.1441 +                ret[i] = new Prprt(e, am, arr[i]);
 13.1442 +                
 13.1443 +            }
 13.1444 +            return ret;
 13.1445 +        }
 13.1446 +        
 13.1447 +        private List<? extends Object> getAnnoValues(ProcessingEnvironment pe) {
 13.1448 +            try {
 13.1449 +                Class<?> trees = Class.forName("com.sun.tools.javac.api.JavacTrees");
 13.1450 +                Method m = trees.getMethod("instance", ProcessingEnvironment.class);
 13.1451 +                Object instance = m.invoke(null, pe);
 13.1452 +                m = instance.getClass().getMethod("getPath", Element.class, AnnotationMirror.class);
 13.1453 +                Object path = m.invoke(instance, e, tm);
 13.1454 +                m = path.getClass().getMethod("getLeaf");
 13.1455 +                Object leaf = m.invoke(path);
 13.1456 +                m = leaf.getClass().getMethod("getArguments");
 13.1457 +                return (List)m.invoke(leaf);
 13.1458 +            } catch (Exception ex) {
 13.1459 +                return Collections.emptyList();
 13.1460 +            }
 13.1461 +        }
 13.1462 +    }
 13.1463 +    
 13.1464  }
    14.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java	Wed Feb 27 17:50:47 2013 +0100
    14.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Canvas.java	Mon Oct 07 14:20:58 2013 +0200
    14.3 @@ -18,6 +18,7 @@
    14.4  package org.apidesign.bck2brwsr.htmlpage.api;
    14.5  
    14.6  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    14.7 +import static org.apidesign.bck2brwsr.htmlpage.api.Element.getAttribute;
    14.8  
    14.9  /**
   14.10   *
   14.11 @@ -34,7 +35,8 @@
   14.12      }
   14.13  
   14.14      public int getHeight() {
   14.15 -        return (Integer) getAttribute(this, "height");
   14.16 +       Object ret =  getAttribute(this, "height");
   14.17 +       return (ret instanceof Number) ? ((Number)ret).intValue(): Integer.MIN_VALUE;
   14.18      }
   14.19      
   14.20      public void setWidth(int width) {
   14.21 @@ -42,7 +44,8 @@
   14.22      }
   14.23  
   14.24      public int getWidth() {
   14.25 -        return (Integer) getAttribute(this, "width");
   14.26 +       Object ret =  getAttribute(this, "width");
   14.27 +       return (ret instanceof Number) ? ((Number)ret).intValue(): Integer.MIN_VALUE;
   14.28      }
   14.29  
   14.30      @JavaScriptBody(
    15.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java	Wed Feb 27 17:50:47 2013 +0100
    15.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/ComputedProperty.java	Mon Oct 07 14:20:58 2013 +0200
    15.3 @@ -22,16 +22,11 @@
    15.4  import java.lang.annotation.RetentionPolicy;
    15.5  import java.lang.annotation.Target;
    15.6  
    15.7 -/** Can be used in classes annotated with {@link Page} annotation to
    15.8 - * define a derived property. Value of derived property is based on values
    15.9 - * of {@link Property} as enumerated by {@link Page#properties()}.
   15.10 - * <p>
   15.11 - * The name of the derived property is the name of the method. The arguments
   15.12 - * of the method define the property names (from {@link Page#properties()} list)
   15.13 - * the value of property depends on. 
   15.14 - *
   15.15 +/** 
   15.16 + * @deprecated Replaced by new {@link net.java.html.json.ComputedProperty net.java.html.json} API.
   15.17   * @author Jaroslav Tulach <jtulach@netbeans.org>
   15.18   */
   15.19 +@Deprecated
   15.20  @Retention(RetentionPolicy.SOURCE)
   15.21  @Target(ElementType.METHOD)
   15.22  public @interface ComputedProperty {
    16.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Wed Feb 27 17:50:47 2013 +0100
    16.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Mon Oct 07 14:20:58 2013 +0200
    16.3 @@ -61,14 +61,18 @@
    16.4      
    16.5      /** Executes given runnable when user performs a "click" on the given
    16.6       * element.
    16.7 +     * @param data an array of one element to fill with event parameter (if any)
    16.8       * @param r the runnable to execute, never null
    16.9       */
   16.10      @JavaScriptBody(
   16.11          args={ "ev", "r" },
   16.12          body="var e = window.document.getElementById(this._id());\n"
   16.13 -           + "e[ev._id()] = function() { r.run__V(); };\n"
   16.14 +           + "e[ev._id()] = function(ev) {\n"
   16.15 +        + "  var d = ev ? ev : null;\n"
   16.16 +        + "  r.onEvent__VLjava_lang_Object_2(d);\n"
   16.17 +        + "};\n"
   16.18      )
   16.19 -    final void on(OnEvent ev, Runnable r) {
   16.20 +    final void on(OnEvent ev, OnHandler r) {
   16.21      }
   16.22  
   16.23      /** Shows alert message dialog in a browser.
    17.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java	Wed Feb 27 17:50:47 2013 +0100
    17.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/GraphicsContext.java	Mon Oct 07 14:20:58 2013 +0200
    17.3 @@ -134,7 +134,7 @@
    17.4      @JavaScriptBody(args = {"ctx", "img", "x", "y"}, body = "ctx.drawImage(img,x,y);")
    17.5      private native static void drawImageImpl(Object ctx, Object img, double x, double y);
    17.6  
    17.7 -    @JavaScriptBody(args = {"style"}, body = "this._context().fillStyle=style;")
    17.8 +    @JavaScriptBody(args = {"style"}, body = "this._context().fillStyle=style.valueOf();")
    17.9      public native void setFillStyle(String style);
   17.10  
   17.11      @JavaScriptBody(args = {}, body = "return this._context().fillStyle;")
   17.12 @@ -155,7 +155,7 @@
   17.13      @JavaScriptBody(args = {"context","obj"}, body = "context.fillStyle=obj;")
   17.14      private native void setFillStyleImpl(Object context, Object obj);
   17.15  
   17.16 -    @JavaScriptBody(args = {"style"}, body = "this._context().strokeStyle=style;")
   17.17 +    @JavaScriptBody(args = {"style"}, body = "this._context().strokeStyle=style.valueOf();")
   17.18      public native void setStrokeStyle(String style);
   17.19  
   17.20      public void setStrokeStyle(LinearGradient style) {
   17.21 @@ -174,7 +174,7 @@
   17.22      @JavaScriptBody(args = {"context","obj"}, body = "context.strokeStyle=obj;")
   17.23      private native void setStrokeStyleImpl(Object context, Object obj);
   17.24  
   17.25 -    @JavaScriptBody(args = {"color"}, body = "this._context().shadowColor=color;")
   17.26 +    @JavaScriptBody(args = {"color"}, body = "this._context().shadowColor=color.valueOf();")
   17.27      public native void setShadowColor(String color);
   17.28  
   17.29      @JavaScriptBody(args = {"blur"}, body = "this._context().shadowBlur=blur;")
   17.30 @@ -204,19 +204,19 @@
   17.31      @JavaScriptBody(args = {}, body = "return this._context().lineCap;")
   17.32      public native String getLineCap();
   17.33  
   17.34 -    @JavaScriptBody(args = {"style"}, body = "this._context().lineCap=style;")
   17.35 +    @JavaScriptBody(args = {"style"}, body = "this._context().lineCap=style.valueOf();")
   17.36      public native void setLineCap(String style);
   17.37  
   17.38      @JavaScriptBody(args = {}, body = "return this._context().lineJoin;")
   17.39      public native String getLineJoin();
   17.40  
   17.41 -    @JavaScriptBody(args = {"style"}, body = "this._context().lineJoin=style;")
   17.42 +    @JavaScriptBody(args = {"style"}, body = "this._context().lineJoin=style.valueOf();")
   17.43      public native void setLineJoin(String style) ;
   17.44  
   17.45      @JavaScriptBody(args = {}, body = "return this._context().lineWidth;")
   17.46      public native double getLineWidth();
   17.47  
   17.48 -    @JavaScriptBody(args = {"width"}, body = "this._context().lineJoin=width;")
   17.49 +    @JavaScriptBody(args = {"width"}, body = "this._context().lineWidth=width;")
   17.50      public native void setLineWidth(double width);
   17.51  
   17.52      @JavaScriptBody(args = {}, body = "return this._context().miterLimit;")
   17.53 @@ -228,19 +228,19 @@
   17.54      @JavaScriptBody(args = {}, body = "return this._context().font;")
   17.55      public native String getFont();
   17.56  
   17.57 -    @JavaScriptBody(args = {"font"}, body = "this._context().font=font;")
   17.58 +    @JavaScriptBody(args = {"font"}, body = "this._context().font=font.valueOf();")
   17.59      public native void setFont(String font);
   17.60  
   17.61      @JavaScriptBody(args = {}, body = "return this._context().textAlign;")
   17.62      public native String getTextAlign();
   17.63  
   17.64 -    @JavaScriptBody(args = {"textalign"}, body = "this._context().textAlign=textalign;")
   17.65 +    @JavaScriptBody(args = {"textalign"}, body = "this._context().textAlign=textalign.valueOf();")
   17.66      public native void setTextAlign(String textAlign);
   17.67  
   17.68      @JavaScriptBody(args = {}, body = "return this._context().textBaseline;")
   17.69      public native String getTextBaseline();
   17.70  
   17.71 -    @JavaScriptBody(args = {"textbaseline"}, body = "this._context().textBaseline=textbaseline;")
   17.72 +    @JavaScriptBody(args = {"textbaseline"}, body = "this._context().textBaseline=textbaseline.valueOf();")
   17.73      public native void setTextBaseline(String textbaseline);
   17.74  
   17.75      @JavaScriptBody(args = {"text", "x", "y"}, body = "this._context().fillText(text,x,y);")
   17.76 @@ -306,7 +306,7 @@
   17.77      @JavaScriptBody(args = {}, body = "return this._context().globalAlpha;")
   17.78      public native double getGlobalAlpha();
   17.79  
   17.80 -    @JavaScriptBody(args = {"operation"}, body = "this._context().globalCompositeOperation=operation;")
   17.81 +    @JavaScriptBody(args = {"operation"}, body = "this._context().globalCompositeOperation=operation.valueOf();")
   17.82      public native void setGlobalCompositeOperation(String operation);
   17.83  
   17.84      @JavaScriptBody(args = {}, body = "return this._context().globalCompositeOperation;")
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Model.java	Mon Oct 07 14:20:58 2013 +0200
    18.3 @@ -0,0 +1,38 @@
    18.4 +/**
    18.5 + * Back 2 Browser Bytecode Translator
    18.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    18.7 + *
    18.8 + * This program is free software: you can redistribute it and/or modify
    18.9 + * it under the terms of the GNU General Public License as published by
   18.10 + * the Free Software Foundation, version 2 of the License.
   18.11 + *
   18.12 + * This program is distributed in the hope that it will be useful,
   18.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   18.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18.15 + * GNU General Public License for more details.
   18.16 + *
   18.17 + * You should have received a copy of the GNU General Public License
   18.18 + * along with this program. Look for COPYING file in the top folder.
   18.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   18.20 + */
   18.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   18.22 +
   18.23 +import java.lang.annotation.ElementType;
   18.24 +import java.lang.annotation.Retention;
   18.25 +import java.lang.annotation.RetentionPolicy;
   18.26 +import java.lang.annotation.Target;
   18.27 +
   18.28 +/** 
   18.29 + * @deprecated Replaced by new {@link net.java.html.json.Model net.java.html.json} API.
   18.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   18.31 + */
   18.32 +@Retention(RetentionPolicy.SOURCE)
   18.33 +@Target(ElementType.TYPE)
   18.34 +@Deprecated
   18.35 +public @interface Model {
   18.36 +    /** Name of the model class */
   18.37 +    String className();
   18.38 +    /** List of properties in the model.
   18.39 +     */
   18.40 +    Property[] properties();
   18.41 +}
    19.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java	Wed Feb 27 17:50:47 2013 +0100
    19.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnController.java	Mon Oct 07 14:20:58 2013 +0200
    19.3 @@ -30,14 +30,33 @@
    19.4          this.arr = arr;
    19.5      }
    19.6      
    19.7 +    /** Registers an event handler on associated {@link OnEvent}
    19.8 +     * and {@link Element}
    19.9 +     * 
   19.10 +     * @param handler the handler to be called when the event occurs
   19.11 +     */
   19.12 +    public void perform(final OnHandler handler) {
   19.13 +        for (Element e : arr) {
   19.14 +            e.on(event, handler);
   19.15 +        }
   19.16 +    }
   19.17 +    
   19.18      /** Registers a runnable to be performed on associated {@link OnEvent} 
   19.19       * and {@link Element}.
   19.20       * 
   19.21       * @see OnEvent#of
   19.22       */
   19.23 -    public void perform(Runnable r) {
   19.24 +    public void perform(final Runnable r) {
   19.25 +        class W implements OnHandler {
   19.26 +            @Override
   19.27 +            public void onEvent(Object event) throws Exception {
   19.28 +                r.run();
   19.29 +            }
   19.30 +        }
   19.31 +        perform(new W());
   19.32 +        OnHandler w = new W();
   19.33          for (Element e : arr) {
   19.34 -            e.on(event, r);
   19.35 +            e.on(event, w);
   19.36          }
   19.37      }
   19.38  }
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnFunction.java	Mon Oct 07 14:20:58 2013 +0200
    20.3 @@ -0,0 +1,33 @@
    20.4 +/**
    20.5 + * Back 2 Browser Bytecode Translator
    20.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    20.7 + *
    20.8 + * This program is free software: you can redistribute it and/or modify
    20.9 + * it under the terms of the GNU General Public License as published by
   20.10 + * the Free Software Foundation, version 2 of the License.
   20.11 + *
   20.12 + * This program is distributed in the hope that it will be useful,
   20.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   20.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   20.15 + * GNU General Public License for more details.
   20.16 + *
   20.17 + * You should have received a copy of the GNU General Public License
   20.18 + * along with this program. Look for COPYING file in the top folder.
   20.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   20.20 + */
   20.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   20.22 +
   20.23 +import java.lang.annotation.ElementType;
   20.24 +import java.lang.annotation.Retention;
   20.25 +import java.lang.annotation.RetentionPolicy;
   20.26 +import java.lang.annotation.Target;
   20.27 +
   20.28 +/** 
   20.29 + * @deprecated Replaced by new {@link net.java.html.json.Function net.java.html.json} API.
   20.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   20.31 + */
   20.32 +@Target(ElementType.METHOD)
   20.33 +@Retention(RetentionPolicy.SOURCE)
   20.34 +@Deprecated
   20.35 +public @interface OnFunction {
   20.36 +}
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnHandler.java	Mon Oct 07 14:20:58 2013 +0200
    21.3 @@ -0,0 +1,33 @@
    21.4 +/**
    21.5 + * Back 2 Browser Bytecode Translator
    21.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    21.7 + *
    21.8 + * This program is free software: you can redistribute it and/or modify
    21.9 + * it under the terms of the GNU General Public License as published by
   21.10 + * the Free Software Foundation, version 2 of the License.
   21.11 + *
   21.12 + * This program is distributed in the hope that it will be useful,
   21.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   21.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   21.15 + * GNU General Public License for more details.
   21.16 + *
   21.17 + * You should have received a copy of the GNU General Public License
   21.18 + * along with this program. Look for COPYING file in the top folder.
   21.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   21.20 + */
   21.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   21.22 +
   21.23 +/** Handler to be called when an event in an HTML {@link Page} appears.
   21.24 + * @see OnEvent
   21.25 + * @see OnController
   21.26 + *
   21.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   21.28 + */
   21.29 +public interface OnHandler {
   21.30 +    /** Called when a DOM event appears
   21.31 +     * 
   21.32 +     * @param event the event as produced by the browser
   21.33 +     * @throws Exception execution can throw exception
   21.34 +     */
   21.35 +    public void onEvent(Object event) throws Exception;
   21.36 +}
    22.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnPropertyChange.java	Mon Oct 07 14:20:58 2013 +0200
    22.3 @@ -0,0 +1,38 @@
    22.4 +/**
    22.5 + * Back 2 Browser Bytecode Translator
    22.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    22.7 + *
    22.8 + * This program is free software: you can redistribute it and/or modify
    22.9 + * it under the terms of the GNU General Public License as published by
   22.10 + * the Free Software Foundation, version 2 of the License.
   22.11 + *
   22.12 + * This program is distributed in the hope that it will be useful,
   22.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   22.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   22.15 + * GNU General Public License for more details.
   22.16 + *
   22.17 + * You should have received a copy of the GNU General Public License
   22.18 + * along with this program. Look for COPYING file in the top folder.
   22.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   22.20 + */
   22.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   22.22 +
   22.23 +import java.lang.annotation.ElementType;
   22.24 +import java.lang.annotation.Retention;
   22.25 +import java.lang.annotation.RetentionPolicy;
   22.26 +import java.lang.annotation.Target;
   22.27 +
   22.28 +/** 
   22.29 + * @deprecated Replaced by new {@link net.java.html.json.OnPropertyChange net.java.html.json} API.
   22.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   22.31 + */
   22.32 +@Retention(RetentionPolicy.SOURCE)
   22.33 +@Target(ElementType.METHOD)
   22.34 +@Deprecated
   22.35 +public @interface OnPropertyChange {
   22.36 +    /** Name(s) of the properties. One wishes to observe.
   22.37 +     * 
   22.38 +     * @return valid java identifier
   22.39 +     */
   22.40 +    String[] value();
   22.41 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnReceive.java	Mon Oct 07 14:20:58 2013 +0200
    23.3 @@ -0,0 +1,53 @@
    23.4 +/**
    23.5 + * Back 2 Browser Bytecode Translator
    23.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    23.7 + *
    23.8 + * This program is free software: you can redistribute it and/or modify
    23.9 + * it under the terms of the GNU General Public License as published by
   23.10 + * the Free Software Foundation, version 2 of the License.
   23.11 + *
   23.12 + * This program is distributed in the hope that it will be useful,
   23.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   23.15 + * GNU General Public License for more details.
   23.16 + *
   23.17 + * You should have received a copy of the GNU General Public License
   23.18 + * along with this program. Look for COPYING file in the top folder.
   23.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   23.20 + */
   23.21 +package org.apidesign.bck2brwsr.htmlpage.api;
   23.22 +
   23.23 +import java.lang.annotation.ElementType;
   23.24 +import java.lang.annotation.Retention;
   23.25 +import java.lang.annotation.RetentionPolicy;
   23.26 +import java.lang.annotation.Target;
   23.27 +
   23.28 +/** 
   23.29 + * @deprecated Replaced by new {@link net.java.html.json.OnReceive net.java.html.json} API.
   23.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   23.31 + * @since 0.6
   23.32 + */
   23.33 +@Retention(RetentionPolicy.SOURCE)
   23.34 +@Target(ElementType.METHOD)
   23.35 +@Deprecated
   23.36 +public @interface OnReceive {
   23.37 +    /** The URL to connect to. Can contain variable names surrounded by '{' and '}'.
   23.38 +     * Those parameters will then become variables of the associated method.
   23.39 +     * 
   23.40 +     * @return the (possibly parametrized) url to connect to
   23.41 +     */
   23.42 +    String url();
   23.43 +    
   23.44 +    /** Support for <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> requires
   23.45 +     * a callback from the server generated page to a function defined in the
   23.46 +     * system. The name of such function is usually specified as a property
   23.47 +     * (of possibly different names). By defining the <code>jsonp</code> attribute
   23.48 +     * one turns on the <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> 
   23.49 +     * transmission and specifies the name of the property. The property should
   23.50 +     * also be used in the {@link #url()} attribute on appropriate place.
   23.51 +     * 
   23.52 +     * @return name of a property to carry the name of <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a>
   23.53 +     *    callback function.
   23.54 +     */
   23.55 +    String jsonp() default "";
   23.56 +}
    24.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java	Wed Feb 27 17:50:47 2013 +0100
    24.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Property.java	Mon Oct 07 14:20:58 2013 +0200
    24.3 @@ -20,15 +20,36 @@
    24.4  import java.lang.annotation.Retention;
    24.5  import java.lang.annotation.RetentionPolicy;
    24.6  import java.lang.annotation.Target;
    24.7 +import java.util.List;
    24.8  
    24.9 -/** Represents a property in a generated model of an HTML
   24.10 - * {@link Page}.
   24.11 - *
   24.12 +/** 
   24.13 + * @deprecated Replaced by new {@link net.java.html.json.Property net.java.html.json} API.
   24.14   * @author Jaroslav Tulach <jtulach@netbeans.org>
   24.15   */
   24.16  @Retention(RetentionPolicy.SOURCE)
   24.17  @Target({})
   24.18 +@Deprecated
   24.19  public @interface Property {
   24.20 +    /** Name of the property. Will be used to define proper getter and setter
   24.21 +     * in the associated class.
   24.22 +     * 
   24.23 +     * @return valid java identifier
   24.24 +     */
   24.25      String name();
   24.26 +    
   24.27 +    /** Type of the property. Can either be primitive type (like <code>int.class</code>,
   24.28 +     * <code>double.class</code>, etc.), {@link String} or complex model
   24.29 +     * class (defined by {@link Model} property).
   24.30 +     * 
   24.31 +     * @return the class of the property
   24.32 +     */
   24.33      Class<?> type();
   24.34 +    
   24.35 +    /** Is this property an array of the {@link #type()} or a single value?
   24.36 +     * If the property is an array, only its getter (returning mutable {@link List} of
   24.37 +     * the boxed {@link #type()}).
   24.38 +     * 
   24.39 +     * @return true, if this is supposed to be an array of values.
   24.40 +     */
   24.41 +    boolean array() default false;
   24.42  }
    25.1 --- a/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js	Wed Feb 27 17:50:47 2013 +0100
    25.2 +++ b/javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js	Mon Oct 07 14:20:58 2013 +0200
    25.3 @@ -2193,7 +2193,14 @@
    25.4                      else
    25.5                          element[attrName] = attrValue;
    25.6                  } else if (!toRemove) {
    25.7 -                    element.setAttribute(attrName, attrValue.toString());
    25.8 +                    try {
    25.9 +                        element.setAttribute(attrName, attrValue.toString());
   25.10 +                    } catch (err) {
   25.11 +                        // ignore for now
   25.12 +                        if (console) {
   25.13 +                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
   25.14 +                        }
   25.15 +                    }
   25.16                  }
   25.17  
   25.18                  // Treat "name" specially - although you can think of it as an attribute, it also needs
    26.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    26.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Compile.java	Mon Oct 07 14:20:58 2013 +0200
    26.3 @@ -0,0 +1,203 @@
    26.4 +/**
    26.5 + * Back 2 Browser Bytecode Translator
    26.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    26.7 + *
    26.8 + * This program is free software: you can redistribute it and/or modify
    26.9 + * it under the terms of the GNU General Public License as published by
   26.10 + * the Free Software Foundation, version 2 of the License.
   26.11 + *
   26.12 + * This program is distributed in the hope that it will be useful,
   26.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   26.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   26.15 + * GNU General Public License for more details.
   26.16 + *
   26.17 + * You should have received a copy of the GNU General Public License
   26.18 + * along with this program. Look for COPYING file in the top folder.
   26.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   26.20 + */
   26.21 +package org.apidesign.bck2brwsr.htmlpage;
   26.22 +
   26.23 +import java.io.ByteArrayInputStream;
   26.24 +import java.io.ByteArrayOutputStream;
   26.25 +import java.io.IOException;
   26.26 +import java.io.InputStream;
   26.27 +import java.io.OutputStream;
   26.28 +import java.net.URI;
   26.29 +import java.net.URISyntaxException;
   26.30 +import java.util.ArrayList;
   26.31 +import java.util.Arrays;
   26.32 +import java.util.HashMap;
   26.33 +import java.util.List;
   26.34 +import java.util.Map;
   26.35 +import java.util.regex.Matcher;
   26.36 +import java.util.regex.Pattern;
   26.37 +import javax.tools.Diagnostic;
   26.38 +import javax.tools.DiagnosticListener;
   26.39 +import javax.tools.FileObject;
   26.40 +import javax.tools.ForwardingJavaFileManager;
   26.41 +import javax.tools.JavaFileManager;
   26.42 +import javax.tools.JavaFileObject;
   26.43 +import javax.tools.JavaFileObject.Kind;
   26.44 +import javax.tools.SimpleJavaFileObject;
   26.45 +import javax.tools.StandardJavaFileManager;
   26.46 +import javax.tools.StandardLocation;
   26.47 +import javax.tools.ToolProvider;
   26.48 +
   26.49 +/**
   26.50 + *
   26.51 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   26.52 + */
   26.53 +final class Compile implements DiagnosticListener<JavaFileObject> {
   26.54 +    private final List<Diagnostic<? extends JavaFileObject>> errors = new ArrayList<>();
   26.55 +    private final Map<String, byte[]> classes;
   26.56 +    private final String pkg;
   26.57 +    private final String cls;
   26.58 +    private final String html;
   26.59 +
   26.60 +    private Compile(String html, String code) throws IOException {
   26.61 +        this.pkg = findPkg(code);
   26.62 +        this.cls = findCls(code);
   26.63 +        this.html = html;
   26.64 +        classes = compile(html, code);
   26.65 +    }
   26.66 +
   26.67 +    /** Performs compilation of given HTML page and associated Java code
   26.68 +     */
   26.69 +    public static Compile create(String html, String code) throws IOException {
   26.70 +        return new Compile(html, code);
   26.71 +    }
   26.72 +    
   26.73 +    /** Checks for given class among compiled resources */
   26.74 +    public byte[] get(String res) {
   26.75 +        return classes.get(res);
   26.76 +    }
   26.77 +    
   26.78 +    /** Obtains errors created during compilation.
   26.79 +     */
   26.80 +    public List<Diagnostic<? extends JavaFileObject>> getErrors() {
   26.81 +        List<Diagnostic<? extends JavaFileObject>> err = new ArrayList<>();
   26.82 +        for (Diagnostic<? extends JavaFileObject> diagnostic : errors) {
   26.83 +            if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   26.84 +                err.add(diagnostic);
   26.85 +            }
   26.86 +        }
   26.87 +        return err;
   26.88 +    }
   26.89 +    
   26.90 +    private Map<String, byte[]> compile(final String html, final String code) throws IOException {
   26.91 +        StandardJavaFileManager sjfm = ToolProvider.getSystemJavaCompiler().getStandardFileManager(this, null, null);
   26.92 +
   26.93 +        final Map<String, ByteArrayOutputStream> class2BAOS = new HashMap<>();
   26.94 +
   26.95 +        JavaFileObject file = new SimpleJavaFileObject(URI.create("mem://mem"), Kind.SOURCE) {
   26.96 +            @Override
   26.97 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
   26.98 +                return code;
   26.99 +            }
  26.100 +        };
  26.101 +        final JavaFileObject htmlFile = new SimpleJavaFileObject(URI.create("mem://mem2"), Kind.OTHER) {
  26.102 +            @Override
  26.103 +            public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  26.104 +                return html;
  26.105 +            }
  26.106 +
  26.107 +            @Override
  26.108 +            public InputStream openInputStream() throws IOException {
  26.109 +                return new ByteArrayInputStream(html.getBytes());
  26.110 +            }
  26.111 +        };
  26.112 +        
  26.113 +        final URI scratch;
  26.114 +        try {
  26.115 +            scratch = new URI("mem://mem3");
  26.116 +        } catch (URISyntaxException ex) {
  26.117 +            throw new IOException(ex);
  26.118 +        }
  26.119 +        
  26.120 +        JavaFileManager jfm = new ForwardingJavaFileManager<JavaFileManager>(sjfm) {
  26.121 +            @Override
  26.122 +            public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
  26.123 +                if (kind  == Kind.CLASS) {
  26.124 +                    final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
  26.125 +
  26.126 +                    class2BAOS.put(className.replace('.', '/') + ".class", buffer);
  26.127 +                    return new SimpleJavaFileObject(sibling.toUri(), kind) {
  26.128 +                        @Override
  26.129 +                        public OutputStream openOutputStream() throws IOException {
  26.130 +                            return buffer;
  26.131 +                        }
  26.132 +                    };
  26.133 +                }
  26.134 +                
  26.135 +                if (kind == Kind.SOURCE) {
  26.136 +                    return new SimpleJavaFileObject(scratch/*sibling.toUri()*/, kind) {
  26.137 +                        private final ByteArrayOutputStream data = new ByteArrayOutputStream();
  26.138 +                        @Override
  26.139 +                        public OutputStream openOutputStream() throws IOException {
  26.140 +                            return data;
  26.141 +                        }
  26.142 +
  26.143 +                        @Override
  26.144 +                        public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
  26.145 +                            data.close();
  26.146 +                            return new String(data.toByteArray());
  26.147 +                        }
  26.148 +                    };
  26.149 +                }
  26.150 +                
  26.151 +                throw new IllegalStateException();
  26.152 +            }
  26.153 +
  26.154 +            @Override
  26.155 +            public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
  26.156 +                if (location == StandardLocation.SOURCE_PATH) {
  26.157 +                    if (packageName.equals(pkg)) {
  26.158 +                        return htmlFile;
  26.159 +                    }
  26.160 +                }
  26.161 +                
  26.162 +                return null;
  26.163 +            }
  26.164 +            
  26.165 +        };
  26.166 +
  26.167 +        ToolProvider.getSystemJavaCompiler().getTask(null, jfm, this, /*XXX:*/Arrays.asList("-source", "1.7", "-target", "1.7"), null, Arrays.asList(file)).call();
  26.168 +
  26.169 +        Map<String, byte[]> result = new HashMap<>();
  26.170 +
  26.171 +        for (Map.Entry<String, ByteArrayOutputStream> e : class2BAOS.entrySet()) {
  26.172 +            result.put(e.getKey(), e.getValue().toByteArray());
  26.173 +        }
  26.174 +
  26.175 +        return result;
  26.176 +    }
  26.177 +
  26.178 +
  26.179 +    @Override
  26.180 +    public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
  26.181 +        errors.add(diagnostic);
  26.182 +    }
  26.183 +    private static String findPkg(String java) throws IOException {
  26.184 +        Pattern p = Pattern.compile("package\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}*;", Pattern.MULTILINE);
  26.185 +        Matcher m = p.matcher(java);
  26.186 +        if (!m.find()) {
  26.187 +            throw new IOException("Can't find package declaration in the java file");
  26.188 +        }
  26.189 +        String pkg = m.group(1);
  26.190 +        return pkg;
  26.191 +    }
  26.192 +    private static String findCls(String java) throws IOException {
  26.193 +        Pattern p = Pattern.compile("class\\p{javaWhitespace}*([\\p{Alnum}\\.]+)\\p{javaWhitespace}", Pattern.MULTILINE);
  26.194 +        Matcher m = p.matcher(java);
  26.195 +        if (!m.find()) {
  26.196 +            throw new IOException("Can't find package declaration in the java file");
  26.197 +        }
  26.198 +        String cls = m.group(1);
  26.199 +        return cls;
  26.200 +    }
  26.201 +
  26.202 +    String getHtml() {
  26.203 +        String fqn = "'" + pkg + '.' + cls + "'";
  26.204 +        return html.replace("'${fqn}'", fqn);
  26.205 +    }
  26.206 +}
    27.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    27.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ConvertTypesTest.java	Mon Oct 07 14:20:58 2013 +0200
    27.3 @@ -0,0 +1,63 @@
    27.4 +/**
    27.5 + * Back 2 Browser Bytecode Translator
    27.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    27.7 + *
    27.8 + * This program is free software: you can redistribute it and/or modify
    27.9 + * it under the terms of the GNU General Public License as published by
   27.10 + * the Free Software Foundation, version 2 of the License.
   27.11 + *
   27.12 + * This program is distributed in the hope that it will be useful,
   27.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   27.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   27.15 + * GNU General Public License for more details.
   27.16 + *
   27.17 + * You should have received a copy of the GNU General Public License
   27.18 + * along with this program. Look for COPYING file in the top folder.
   27.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   27.20 + */
   27.21 +package org.apidesign.bck2brwsr.htmlpage;
   27.22 +
   27.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   27.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   27.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   27.26 +import org.testng.annotations.Factory;
   27.27 +
   27.28 +/**
   27.29 + *
   27.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   27.31 + */
   27.32 +public class ConvertTypesTest {
   27.33 +    @JavaScriptBody(args = { "includeSex" }, body = "var json = new Object();"
   27.34 +        + "json.firstName = 'son';\n"
   27.35 +        + "json.lastName = 'dj';\n"
   27.36 +        + "if (includeSex) json.sex = 'MALE';\n"
   27.37 +        + "return json;"
   27.38 +    )
   27.39 +    private static native Object createJSON(boolean includeSex);
   27.40 +    
   27.41 +    @BrwsrTest
   27.42 +    public void testConvertToPeople() throws Exception {
   27.43 +        final Object o = createJSON(true);
   27.44 +        
   27.45 +        Person p = new Person(o);
   27.46 +        
   27.47 +        assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
   27.48 +        assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
   27.49 +        assert Sex.MALE.equals(p.getSex()) : "Sex: " + p.getSex();
   27.50 +    }
   27.51 +
   27.52 +    @BrwsrTest
   27.53 +    public void testConvertToPeopleWithoutSex() throws Exception {
   27.54 +        final Object o = createJSON(false);
   27.55 +        
   27.56 +        Person p = new Person(o);
   27.57 +        
   27.58 +        assert "son".equals(p.getFirstName()) : "First name: " + p.getFirstName();
   27.59 +        assert "dj".equals(p.getLastName()) : "Last name: " + p.getLastName();
   27.60 +        assert p.getSex() == null : "No sex: " + p.getSex();
   27.61 +    }
   27.62 +    
   27.63 +    @Factory public static Object[] create() {
   27.64 +        return VMTest.create(ConvertTypesTest.class);
   27.65 +    }
   27.66 +}
   27.67 \ No newline at end of file
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/JSONTest.java	Mon Oct 07 14:20:58 2013 +0200
    28.3 @@ -0,0 +1,392 @@
    28.4 +/**
    28.5 + * Back 2 Browser Bytecode Translator
    28.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    28.7 + *
    28.8 + * This program is free software: you can redistribute it and/or modify
    28.9 + * it under the terms of the GNU General Public License as published by
   28.10 + * the Free Software Foundation, version 2 of the License.
   28.11 + *
   28.12 + * This program is distributed in the hope that it will be useful,
   28.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   28.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   28.15 + * GNU General Public License for more details.
   28.16 + *
   28.17 + * You should have received a copy of the GNU General Public License
   28.18 + * along with this program. Look for COPYING file in the top folder.
   28.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   28.20 + */
   28.21 +package org.apidesign.bck2brwsr.htmlpage;
   28.22 +
   28.23 +import java.util.Arrays;
   28.24 +import java.util.Iterator;
   28.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   28.26 +import org.apidesign.bck2brwsr.htmlpage.api.OnReceive;
   28.27 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
   28.28 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
   28.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   28.30 +import org.apidesign.bck2brwsr.vmtest.Http;
   28.31 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   28.32 +import org.json.JSONException;
   28.33 +import org.json.JSONObject;
   28.34 +import org.json.JSONTokener;
   28.35 +import org.testng.annotations.Test;
   28.36 +import static org.testng.Assert.*;
   28.37 +import org.testng.annotations.Factory;
   28.38 +
   28.39 +/** Need to verify that models produce reasonable JSON objects.
   28.40 + *
   28.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   28.42 + */
   28.43 +@Page(xhtml = "Empty.html", className = "JSONik", properties = {
   28.44 +    @Property(name = "fetched", type = PersonImpl.class),
   28.45 +    @Property(name = "fetchedCount", type = int.class),
   28.46 +    @Property(name = "fetchedSex", type = Sex.class, array = true)
   28.47 +})
   28.48 +public class JSONTest {
   28.49 +    private JSONik js;
   28.50 +    private Integer orig;
   28.51 +    
   28.52 +    @Test public void personToString() throws JSONException {
   28.53 +        Person p = new Person();
   28.54 +        p.setSex(Sex.MALE);
   28.55 +        p.setFirstName("Jarda");
   28.56 +        p.setLastName("Tulach");
   28.57 +        
   28.58 +        JSONTokener t = new JSONTokener(p.toString());
   28.59 +        JSONObject o;
   28.60 +        try {
   28.61 +            o = new JSONObject(t);
   28.62 +        } catch (JSONException ex) {
   28.63 +            throw new AssertionError("Can't parse " + p.toString(), ex);
   28.64 +        }
   28.65 +        
   28.66 +        Iterator it = o.sortedKeys();
   28.67 +        assertEquals(it.next(), "firstName");
   28.68 +        assertEquals(it.next(), "lastName");
   28.69 +        assertEquals(it.next(), "sex");
   28.70 +        
   28.71 +        assertEquals(o.getString("firstName"), "Jarda");
   28.72 +        assertEquals(o.getString("lastName"), "Tulach");
   28.73 +        assertEquals(o.getString("sex"), "MALE");
   28.74 +    }
   28.75 +    
   28.76 +    @BrwsrTest public void toJSONInABrowser() throws Throwable {
   28.77 +        Person p = new Person();
   28.78 +        p.setSex(Sex.MALE);
   28.79 +        p.setFirstName("Jarda");
   28.80 +        p.setLastName("Tulach");
   28.81 +
   28.82 +        Object json;
   28.83 +        try {
   28.84 +            json = parseJSON(p.toString());
   28.85 +        } catch (Throwable ex) {
   28.86 +            throw new IllegalStateException("Can't parse " + p).initCause(ex);
   28.87 +        }
   28.88 +        
   28.89 +        Person p2 = new Person(json);
   28.90 +        
   28.91 +        assert p2.getFirstName().equals(p.getFirstName()) : 
   28.92 +            "Should be the same: " + p.getFirstName() + " != " + p2.getFirstName();
   28.93 +    }
   28.94 +    
   28.95 +    @Test public void personWithWildCharactersAndNulls() throws JSONException {
   28.96 +        Person p = new Person();
   28.97 +        p.setFirstName("'\"\n");
   28.98 +        p.setLastName("\t\r\u0002");
   28.99 +        
  28.100 +        JSONTokener t = new JSONTokener(p.toString());
  28.101 +        JSONObject o;
  28.102 +        try {
  28.103 +            o = new JSONObject(t);
  28.104 +        } catch (JSONException ex) {
  28.105 +            throw new AssertionError("Can't parse " + p.toString(), ex);
  28.106 +        }
  28.107 +        
  28.108 +        Iterator it = o.sortedKeys();
  28.109 +        assertEquals(it.next(), "firstName");
  28.110 +        assertEquals(it.next(), "lastName");
  28.111 +        assertEquals(it.next(), "sex");
  28.112 +        
  28.113 +        assertEquals(o.getString("firstName"), p.getFirstName());
  28.114 +        assertEquals(o.getString("lastName"), p.getLastName());
  28.115 +        assertEquals(o.get("sex"), JSONObject.NULL);
  28.116 +    }
  28.117 +    
  28.118 +    @Test public void personsInArray() throws JSONException {
  28.119 +        Person p1 = new Person();
  28.120 +        p1.setFirstName("One");
  28.121 +
  28.122 +        Person p2 = new Person();
  28.123 +        p2.setFirstName("Two");
  28.124 +        
  28.125 +        People arr = new People();
  28.126 +        arr.getInfo().add(p1);
  28.127 +        arr.getInfo().add(p2);
  28.128 +        arr.getNicknames().add("Prvn\u00ed k\u016f\u0148");
  28.129 +        final String n2 = "Druh\u00fd hlem\u00fd\u017e\u010f, star\u0161\u00ed";
  28.130 +        arr.getNicknames().add(n2);
  28.131 +        arr.getAge().add(33);
  28.132 +        arr.getAge().add(73);
  28.133 +        
  28.134 +        
  28.135 +        final String json = arr.toString();
  28.136 +        
  28.137 +        JSONTokener t = new JSONTokener(json);
  28.138 +        JSONObject o;
  28.139 +        try {
  28.140 +            o = new JSONObject(t);
  28.141 +        } catch (JSONException ex) {
  28.142 +            throw new AssertionError("Can't parse " + json, ex);
  28.143 +        }
  28.144 +
  28.145 +        assertEquals(o.getJSONArray("info").getJSONObject(0).getString("firstName"), "One");
  28.146 +        assertEquals(o.getJSONArray("nicknames").getString(1), n2);
  28.147 +        assertEquals(o.getJSONArray("age").getInt(1), 73);
  28.148 +    }
  28.149 +    
  28.150 +    
  28.151 +    @OnReceive(url="/{url}")
  28.152 +    static void fetch(Person p, JSONik model) {
  28.153 +        model.setFetched(p);
  28.154 +    }
  28.155 +
  28.156 +    @OnReceive(url="/{url}")
  28.157 +    static void fetchArray(Person[] p, JSONik model) {
  28.158 +        model.setFetchedCount(p.length);
  28.159 +        model.setFetched(p[0]);
  28.160 +    }
  28.161 +    
  28.162 +    @OnReceive(url="/{url}")
  28.163 +    static void fetchPeople(People p, JSONik model) {
  28.164 +        model.setFetchedCount(p.getInfo().size());
  28.165 +        model.setFetched(p.getInfo().get(0));
  28.166 +    }
  28.167 +
  28.168 +    @OnReceive(url="/{url}")
  28.169 +    static void fetchPeopleAge(People p, JSONik model) {
  28.170 +        int sum = 0;
  28.171 +        for (int a : p.getAge()) {
  28.172 +            sum += a;
  28.173 +        }
  28.174 +        model.setFetchedCount(sum);
  28.175 +    }
  28.176 +    
  28.177 +    @Http(@Http.Resource(
  28.178 +        content = "{'firstName': 'Sitar', 'sex': 'MALE'}", 
  28.179 +        path="/person.json", 
  28.180 +        mimeType = "application/json"
  28.181 +    ))
  28.182 +    @BrwsrTest public void loadAndParseJSON() throws InterruptedException {
  28.183 +        if (js == null) {
  28.184 +            js = new JSONik();
  28.185 +            js.applyBindings();
  28.186 +
  28.187 +            js.fetch("person.json");
  28.188 +        }
  28.189 +    
  28.190 +        Person p = js.getFetched();
  28.191 +        if (p == null) {
  28.192 +            throw new InterruptedException();
  28.193 +        }
  28.194 +        
  28.195 +        assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
  28.196 +        assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
  28.197 +    }
  28.198 +    
  28.199 +    @OnReceive(url="/{url}?callme={me}", jsonp = "me")
  28.200 +    static void fetchViaJSONP(Person p, JSONik model) {
  28.201 +        model.setFetched(p);
  28.202 +    }
  28.203 +    
  28.204 +    @Http(@Http.Resource(
  28.205 +        content = "$0({'firstName': 'Mitar', 'sex': 'MALE'})", 
  28.206 +        path="/person.json", 
  28.207 +        mimeType = "application/javascript",
  28.208 +        parameters = { "callme" }
  28.209 +    ))
  28.210 +    @BrwsrTest public void loadAndParseJSONP() throws InterruptedException {
  28.211 +        
  28.212 +        if (js == null) {
  28.213 +            orig = scriptElements();
  28.214 +            assert orig > 0 : "There should be some scripts on the page";
  28.215 +            
  28.216 +            js = new JSONik();
  28.217 +            js.applyBindings();
  28.218 +
  28.219 +            js.fetchViaJSONP("person.json");
  28.220 +        }
  28.221 +    
  28.222 +        Person p = js.getFetched();
  28.223 +        if (p == null) {
  28.224 +            throw new InterruptedException();
  28.225 +        }
  28.226 +        
  28.227 +        assert "Mitar".equals(p.getFirstName()) : "Unexpected: " + p.getFirstName();
  28.228 +        assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
  28.229 +        
  28.230 +        int now = scriptElements();
  28.231 +        
  28.232 +        assert orig == now : "The set of elements is unchanged. Delta: " + (now - orig);
  28.233 +    }
  28.234 +    
  28.235 +    @JavaScriptBody(args = {  }, body = "return window.document.getElementsByTagName('script').length;")
  28.236 +    private static native int scriptElements();
  28.237 +
  28.238 +    @JavaScriptBody(args = { "s" }, body = "return window.JSON.parse(s);")
  28.239 +    private static native Object parseJSON(String s);
  28.240 +    
  28.241 +    @Http(@Http.Resource(
  28.242 +        content = "{'firstName': 'Sitar', 'sex': 'MALE'}", 
  28.243 +        path="/person.json", 
  28.244 +        mimeType = "application/json"
  28.245 +    ))
  28.246 +    @BrwsrTest public void loadAndParseJSONSentToArray() throws InterruptedException {
  28.247 +        if (js == null) {
  28.248 +            js = new JSONik();
  28.249 +            js.applyBindings();
  28.250 +
  28.251 +            js.fetchArray("person.json");
  28.252 +        }
  28.253 +        
  28.254 +        Person p = js.getFetched();
  28.255 +        if (p == null) {
  28.256 +            throw new InterruptedException();
  28.257 +        }
  28.258 +        
  28.259 +        assert p != null : "We should get our person back: " + p;
  28.260 +        assert "Sitar".equals(p.getFirstName()) : "Expecting Sitar: " + p.getFirstName();
  28.261 +        assert Sex.MALE.equals(p.getSex()) : "Expecting MALE: " + p.getSex();
  28.262 +    }
  28.263 +    
  28.264 +    @Http(@Http.Resource(
  28.265 +        content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'}]", 
  28.266 +        path="/person.json", 
  28.267 +        mimeType = "application/json"
  28.268 +    ))
  28.269 +    @BrwsrTest public void loadAndParseJSONArraySingle() throws InterruptedException {
  28.270 +        if (js == null) {
  28.271 +            js = new JSONik();
  28.272 +            js.applyBindings();
  28.273 +        
  28.274 +            js.fetch("person.json");
  28.275 +        }
  28.276 +        
  28.277 +        Person p = js.getFetched();
  28.278 +        if (p == null) {
  28.279 +            throw new InterruptedException();
  28.280 +        }
  28.281 +        
  28.282 +        assert p != null : "We should get our person back: " + p;
  28.283 +        assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
  28.284 +        assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
  28.285 +    }
  28.286 +    
  28.287 +    @Http(@Http.Resource(
  28.288 +        content = "{'info':[{'firstName': 'Gitar', 'sex': 'FEMALE'}]}", 
  28.289 +        path="/people.json", 
  28.290 +        mimeType = "application/json"
  28.291 +    ))
  28.292 +    @BrwsrTest public void loadAndParseArrayInPeople() throws InterruptedException {
  28.293 +        if (js == null) {
  28.294 +            js = new JSONik();
  28.295 +            js.applyBindings();
  28.296 +        
  28.297 +            js.fetchPeople("people.json");
  28.298 +        }
  28.299 +        
  28.300 +        if (0 == js.getFetchedCount()) {
  28.301 +            throw new InterruptedException();
  28.302 +        }
  28.303 +
  28.304 +        assert js.getFetchedCount() == 1 : "One person loaded: " + js.getFetchedCount();
  28.305 +        
  28.306 +        Person p = js.getFetched();
  28.307 +        
  28.308 +        assert p != null : "We should get our person back: " + p;
  28.309 +        assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
  28.310 +        assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
  28.311 +    }
  28.312 +    
  28.313 +    @Http(@Http.Resource(
  28.314 +        content = "{'age':[1, 2, 3]}", 
  28.315 +        path="/people.json", 
  28.316 +        mimeType = "application/json"
  28.317 +    ))
  28.318 +    @BrwsrTest public void loadAndParseArrayOfIntegers() throws InterruptedException {
  28.319 +        if (js == null) {
  28.320 +            js = new JSONik();
  28.321 +            js.applyBindings();
  28.322 +        
  28.323 +            js.fetchPeopleAge("people.json");
  28.324 +        }
  28.325 +        
  28.326 +        if (0 == js.getFetchedCount()) {
  28.327 +            throw new InterruptedException();
  28.328 +        }
  28.329 +
  28.330 +        assert js.getFetchedCount() == 6 : "1 + 2 + 3 is " + js.getFetchedCount();
  28.331 +    }
  28.332 +    
  28.333 +    @OnReceive(url="/{url}")
  28.334 +    static void fetchPeopleSex(People p, JSONik model) {
  28.335 +        model.setFetchedCount(1);
  28.336 +        model.getFetchedSex().addAll(p.getSex());
  28.337 +    }
  28.338 +    
  28.339 +    
  28.340 +    @Http(@Http.Resource(
  28.341 +        content = "{'sex':['FEMALE', 'MALE', 'MALE']}", 
  28.342 +        path="/people.json", 
  28.343 +        mimeType = "application/json"
  28.344 +    ))
  28.345 +    @BrwsrTest public void loadAndParseArrayOfEnums() throws InterruptedException {
  28.346 +        if (js == null) {
  28.347 +            js = new JSONik();
  28.348 +            js.applyBindings();
  28.349 +        
  28.350 +            js.fetchPeopleSex("people.json");
  28.351 +        }
  28.352 +        
  28.353 +        if (0 == js.getFetchedCount()) {
  28.354 +            throw new InterruptedException();
  28.355 +        }
  28.356 +
  28.357 +        assert js.getFetchedCount() == 1 : "Loaded";
  28.358 +        
  28.359 +        assert js.getFetchedSex().size() == 3 : "Three values " + js.getFetchedSex();
  28.360 +        assert js.getFetchedSex().get(0) == Sex.FEMALE : "Female first " + js.getFetchedSex();
  28.361 +        assert js.getFetchedSex().get(1) == Sex.MALE : "male 2nd " + js.getFetchedSex();
  28.362 +        assert js.getFetchedSex().get(2) == Sex.MALE : "male 3rd " + js.getFetchedSex();
  28.363 +    }
  28.364 +    
  28.365 +    @Http(@Http.Resource(
  28.366 +        content = "[{'firstName': 'Gitar', 'sex': 'FEMALE'},"
  28.367 +        + "{'firstName': 'Peter', 'sex': 'MALE'}"
  28.368 +        + "]", 
  28.369 +        path="/person.json", 
  28.370 +        mimeType = "application/json"
  28.371 +    ))
  28.372 +    @BrwsrTest public void loadAndParseJSONArray() throws InterruptedException {
  28.373 +        if (js == null) {
  28.374 +            js = new JSONik();
  28.375 +            js.applyBindings();
  28.376 +            js.fetchArray("person.json");
  28.377 +        }
  28.378 +        
  28.379 +        
  28.380 +        Person p = js.getFetched();
  28.381 +        if (p == null) {
  28.382 +            throw new InterruptedException();
  28.383 +        }
  28.384 +        
  28.385 +        assert js.getFetchedCount() == 2 : "We got two values: " + js.getFetchedCount();
  28.386 +        assert p != null : "We should get our person back: " + p;
  28.387 +        assert "Gitar".equals(p.getFirstName()) : "Expecting Gitar: " + p.getFirstName();
  28.388 +        assert Sex.FEMALE.equals(p.getSex()) : "Expecting FEMALE: " + p.getSex();
  28.389 +    }
  28.390 +
  28.391 +    @Factory public static Object[] create() {
  28.392 +        return VMTest.create(JSONTest.class);
  28.393 +    }
  28.394 +    
  28.395 +}
    29.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java	Wed Feb 27 17:50:47 2013 +0100
    29.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java	Mon Oct 07 14:20:58 2013 +0200
    29.3 @@ -17,21 +17,29 @@
    29.4   */
    29.5  package org.apidesign.bck2brwsr.htmlpage;
    29.6  
    29.7 +import java.util.List;
    29.8 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
    29.9  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   29.10  import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
   29.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   29.12  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   29.13  import org.apidesign.bck2brwsr.htmlpage.api.Property;
   29.14  import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   29.15  import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
   29.16  import org.apidesign.bck2brwsr.vmtest.VMTest;
   29.17 +import static org.testng.Assert.assertEquals;
   29.18  import org.testng.annotations.Factory;
   29.19 +import org.testng.annotations.Test;
   29.20  
   29.21  /**
   29.22   *
   29.23   * @author Jaroslav Tulach <jtulach@netbeans.org>
   29.24   */
   29.25  @Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={
   29.26 -    @Property(name="name", type=String.class)
   29.27 +    @Property(name="name", type=String.class),
   29.28 +    @Property(name="results", type=String.class, array = true),
   29.29 +    @Property(name="callbackCount", type=int.class),
   29.30 +    @Property(name="people", type=PersonImpl.class, array = true)
   29.31  }) 
   29.32  public class KnockoutTest {
   29.33      
   29.34 @@ -44,19 +52,207 @@
   29.35          KnockoutModel m = new KnockoutModel();
   29.36          m.setName("Kukuc");
   29.37          m.applyBindings();
   29.38 -        assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue();
   29.39 -        m.INPUT.setValue("Jardo");
   29.40 -        m.triggerEvent(m.INPUT, OnEvent.CHANGE);
   29.41 +        assert "Kukuc".equals(m.input.getValue()) : "Value is really kukuc: " + m.input.getValue();
   29.42 +        m.input.setValue("Jardo");
   29.43 +        m.triggerEvent(m.input, OnEvent.CHANGE);
   29.44          assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
   29.45      }
   29.46      
   29.47 +    @HtmlFragment(
   29.48 +        "<ul id='ul' data-bind='foreach: results'>\n"
   29.49 +        + "  <li data-bind='text: $data, click: $root.call'/>\n"
   29.50 +        + "</ul>\n"
   29.51 +    )
   29.52 +    @BrwsrTest public void displayContentOfArray() {
   29.53 +        KnockoutModel m = new KnockoutModel();
   29.54 +        m.getResults().add("Ahoj");
   29.55 +        m.applyBindings();
   29.56 +        
   29.57 +        int cnt = countChildren("ul");
   29.58 +        assert cnt == 1 : "One child, but was " + cnt;
   29.59 +        
   29.60 +        m.getResults().add("Hi");
   29.61 +
   29.62 +        cnt = countChildren("ul");
   29.63 +        assert cnt == 2 : "Two children now, but was " + cnt;
   29.64 +        
   29.65 +        triggerChildClick("ul", 1);
   29.66 +        
   29.67 +        assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
   29.68 +        assert "Hi".equals(m.getName()) : "We got callback from 2nd child " + m.getName();
   29.69 +    }
   29.70 +    
   29.71 +    @HtmlFragment(
   29.72 +        "<ul id='ul' data-bind='foreach: cmpResults'>\n"
   29.73 +        + "  <li><b data-bind='text: $data'></b></li>\n"
   29.74 +        + "</ul>\n"
   29.75 +    )
   29.76 +    @BrwsrTest public void displayContentOfDerivedArray() {
   29.77 +        KnockoutModel m = new KnockoutModel();
   29.78 +        m.getResults().add("Ahoj");
   29.79 +        m.applyBindings();
   29.80 +        
   29.81 +        int cnt = countChildren("ul");
   29.82 +        assert cnt == 1 : "One child, but was " + cnt;
   29.83 +        
   29.84 +        m.getResults().add("hello");
   29.85 +
   29.86 +        cnt = countChildren("ul");
   29.87 +        assert cnt == 2 : "Two children now, but was " + cnt;
   29.88 +    }
   29.89 +    
   29.90 +    @HtmlFragment(
   29.91 +        "<ul id='ul' data-bind='foreach: people'>\n"
   29.92 +        + "  <li data-bind='text: $data.firstName, click: $root.removePerson'></li>\n"
   29.93 +        + "</ul>\n"
   29.94 +    )
   29.95 +    @BrwsrTest public void displayContentOfArrayOfPeople() {
   29.96 +        KnockoutModel m = new KnockoutModel();
   29.97 +        
   29.98 +        final Person first = new Person();
   29.99 +        first.setFirstName("first");
  29.100 +        m.getPeople().add(first);
  29.101 +        
  29.102 +        m.applyBindings();
  29.103 +        
  29.104 +        int cnt = countChildren("ul");
  29.105 +        assert cnt == 1 : "One child, but was " + cnt;
  29.106 +        
  29.107 +        final Person second = new Person();
  29.108 +        second.setFirstName("second");
  29.109 +        m.getPeople().add(second);
  29.110 +
  29.111 +        cnt = countChildren("ul");
  29.112 +        assert cnt == 2 : "Two children now, but was " + cnt;
  29.113 +
  29.114 +        triggerChildClick("ul", 1);
  29.115 +        
  29.116 +        assert 1 == m.getCallbackCount() : "One callback " + m.getCallbackCount();
  29.117 +
  29.118 +        cnt = countChildren("ul");
  29.119 +        assert cnt == 1 : "Again one child, but was " + cnt;
  29.120 +        
  29.121 +        String txt = childText("ul", 0);
  29.122 +        assert "first".equals(txt) : "Expecting 'first': " + txt;
  29.123 +        
  29.124 +        first.setFirstName("changed");
  29.125 +        
  29.126 +        txt = childText("ul", 0);
  29.127 +        assert "changed".equals(txt) : "Expecting 'changed': " + txt;
  29.128 +    }
  29.129 +    
  29.130 +    @ComputedProperty
  29.131 +    static Person firstPerson(List<Person> people) {
  29.132 +        return people.isEmpty() ? null : people.get(0);
  29.133 +    }
  29.134 +    
  29.135 +    @HtmlFragment(
  29.136 +        "<p id='ul' data-bind='with: firstPerson'>\n"
  29.137 +        + "  <span data-bind='text: firstName, click: changeSex'></span>\n"
  29.138 +        + "</p>\n"
  29.139 +    )
  29.140 +    @BrwsrTest public void accessFirstPersonWithOnFunction() {
  29.141 +        trasfertToFemale();
  29.142 +    }
  29.143 +    
  29.144 +    @HtmlFragment(
  29.145 +        "<ul id='ul' data-bind='foreach: people'>\n"
  29.146 +        + "  <li data-bind='text: $data.firstName, click: changeSex'></li>\n"
  29.147 +        + "</ul>\n"
  29.148 +    )
  29.149 +    @BrwsrTest public void onPersonFunction() {
  29.150 +        trasfertToFemale();
  29.151 +    }
  29.152 +    
  29.153 +    private void trasfertToFemale() {
  29.154 +        KnockoutModel m = new KnockoutModel();
  29.155 +
  29.156 +        final Person first = new Person();
  29.157 +        first.setFirstName("first");
  29.158 +        first.setSex(Sex.MALE);
  29.159 +        m.getPeople().add(first);
  29.160 +
  29.161 +
  29.162 +        m.applyBindings();
  29.163 +
  29.164 +        int cnt = countChildren("ul");
  29.165 +        assert cnt == 1 : "One child, but was " + cnt;
  29.166 +
  29.167 +
  29.168 +        triggerChildClick("ul", 0);
  29.169 +
  29.170 +        assert first.getSex() == Sex.FEMALE : "Transverted to female: " + first.getSex();
  29.171 +    }
  29.172 +    
  29.173 +    @Test public void cloneModel() {
  29.174 +        Person model = new Person();
  29.175 +        
  29.176 +        model.setFirstName("first");
  29.177 +        Person snd = model.clone();
  29.178 +        snd.setFirstName("clone");
  29.179 +        assertEquals("first", model.getFirstName(), "Value has not changed");
  29.180 +        assertEquals("clone", snd.getFirstName(), "Value has changed in clone");
  29.181 +    }
  29.182 +   
  29.183 +    
  29.184 +    @Test public void deepCopyOnClone() {
  29.185 +        People model = new People();
  29.186 +        model.getNicknames().add("Jarda");
  29.187 +        assertEquals(model.getNicknames().size(), 1, "One element");
  29.188 +        People snd = model.clone();
  29.189 +        snd.getNicknames().clear();
  29.190 +        assertEquals(snd.getNicknames().size(), 0, "Clone is empty");
  29.191 +        assertEquals(model.getNicknames().size(), 1, "Still one element");
  29.192 +    }
  29.193 +    
  29.194 +     
  29.195 +    @OnFunction
  29.196 +    static void call(KnockoutModel m, String data) {
  29.197 +        m.setName(data);
  29.198 +        m.setCallbackCount(m.getCallbackCount() + 1);
  29.199 +    }
  29.200 +
  29.201 +    @OnFunction
  29.202 +    static void removePerson(KnockoutModel model, Person data) {
  29.203 +        model.setCallbackCount(model.getCallbackCount() + 1);
  29.204 +        model.getPeople().remove(data);
  29.205 +    }
  29.206 +    
  29.207 +    
  29.208      @ComputedProperty
  29.209      static String helloMessage(String name) {
  29.210          return "Hello " + name + "!";
  29.211      }
  29.212      
  29.213 +    @ComputedProperty
  29.214 +    static List<String> cmpResults(List<String> results) {
  29.215 +        return results;
  29.216 +    }
  29.217 +    
  29.218      @Factory
  29.219      public static Object[] create() {
  29.220          return VMTest.create(KnockoutTest.class);
  29.221      }
  29.222 +    
  29.223 +    @JavaScriptBody(args = { "id" }, body = 
  29.224 +          "var e = window.document.getElementById(id);\n "
  29.225 +        + "if (typeof e === 'undefined') return -2;\n "
  29.226 +        + "return e.children.length;\n "
  29.227 +    )
  29.228 +    private static native int countChildren(String id);
  29.229 +
  29.230 +    @JavaScriptBody(args = { "id", "pos" }, body = 
  29.231 +          "var e = window.document.getElementById(id);\n "
  29.232 +        + "var ev = window.document.createEvent('MouseEvents');\n "
  29.233 +        + "ev.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);\n "
  29.234 +        + "e.children[pos].dispatchEvent(ev);\n "
  29.235 +    )
  29.236 +    private static native void triggerChildClick(String id, int pos);
  29.237 +
  29.238 +    @JavaScriptBody(args = { "id", "pos" }, body = 
  29.239 +          "var e = window.document.getElementById(id);\n "
  29.240 +        + "var t = e.children[pos].innerHTML;\n "
  29.241 +        + "return t ? t : null;"
  29.242 +    )
  29.243 +    private static native String childText(String id, int pos);
  29.244  }
    30.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java	Wed Feb 27 17:50:47 2013 +0100
    30.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ModelTest.java	Mon Oct 07 14:20:58 2013 +0200
    30.3 @@ -18,8 +18,13 @@
    30.4  package org.apidesign.bck2brwsr.htmlpage;
    30.5  
    30.6  import java.util.ArrayList;
    30.7 +import java.util.Collections;
    30.8 +import java.util.Iterator;
    30.9  import java.util.List;
   30.10 +import java.util.ListIterator;
   30.11  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   30.12 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   30.13 +import org.apidesign.bck2brwsr.htmlpage.api.OnPropertyChange;
   30.14  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   30.15  import org.apidesign.bck2brwsr.htmlpage.api.Property;
   30.16  import static org.testng.Assert.*;
   30.17 @@ -30,17 +35,22 @@
   30.18   *
   30.19   * @author Jaroslav Tulach <jtulach@netbeans.org>
   30.20   */
   30.21 -@Page(xhtml = "Empty.html", className = "Model", properties = {
   30.22 +@Page(xhtml = "Empty.html", className = "Modelik", properties = {
   30.23      @Property(name = "value", type = int.class),
   30.24 -    @Property(name = "unrelated", type = long.class)
   30.25 +    @Property(name = "count", type = int.class),
   30.26 +    @Property(name = "unrelated", type = long.class),
   30.27 +    @Property(name = "names", type = String.class, array = true),
   30.28 +    @Property(name = "values", type = int.class, array = true),
   30.29 +    @Property(name = "people", type = PersonImpl.class, array = true),
   30.30 +    @Property(name = "changedProperty", type=String.class)
   30.31  })
   30.32  public class ModelTest {
   30.33 -    private Model model;
   30.34 -    private static Model leakedModel;
   30.35 +    private Modelik model;
   30.36 +    private static Modelik leakedModel;
   30.37      
   30.38      @BeforeMethod
   30.39      public void createModel() {
   30.40 -        model = new Model();
   30.41 +        model = new Modelik();
   30.42      }
   30.43      
   30.44      @Test public void classGeneratedWithSetterGetter() {
   30.45 @@ -53,6 +63,75 @@
   30.46          assertEquals(16, model.getPowerValue());
   30.47      }
   30.48      
   30.49 +    @Test public void arrayIsMutable() {
   30.50 +        assertEquals(model.getNames().size(), 0, "Is empty");
   30.51 +        model.getNames().add("Jarda");
   30.52 +        assertEquals(model.getNames().size(), 1, "One element");
   30.53 +    }
   30.54 +    
   30.55 +    @Test public void arrayChangesNotified() {
   30.56 +        MockKnockout my = new MockKnockout();
   30.57 +        MockKnockout.next = my;
   30.58 +        
   30.59 +        model.applyBindings();
   30.60 +        
   30.61 +        model.getNames().add("Hello");
   30.62 +        
   30.63 +        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   30.64 +        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   30.65 +
   30.66 +        my.mutated.clear();
   30.67 +        
   30.68 +        Iterator<String> it = model.getNames().iterator();
   30.69 +        assertEquals(it.next(), "Hello");
   30.70 +        it.remove();
   30.71 +        
   30.72 +        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   30.73 +        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   30.74 +
   30.75 +        my.mutated.clear();
   30.76 +        
   30.77 +        ListIterator<String> lit = model.getNames().listIterator();
   30.78 +        lit.add("Jarda");
   30.79 +        
   30.80 +        assertFalse(my.mutated.isEmpty(), "There was a change" + my.mutated);
   30.81 +        assertTrue(my.mutated.contains("names"), "Change in names property: " + my.mutated);
   30.82 +    }
   30.83 +    
   30.84 +    @Test public void autoboxedArray() {
   30.85 +        MockKnockout my = new MockKnockout();
   30.86 +        MockKnockout.next = my;
   30.87 +        
   30.88 +        model.applyBindings();
   30.89 +        
   30.90 +        model.getValues().add(10);
   30.91 +        
   30.92 +        assertEquals(model.getValues().get(0), Integer.valueOf(10), "Really ten");
   30.93 +    }
   30.94 +
   30.95 +    @Test public void derivedArrayProp() {
   30.96 +        MockKnockout my = new MockKnockout();
   30.97 +        MockKnockout.next = my;
   30.98 +        
   30.99 +        model.applyBindings();
  30.100 +        
  30.101 +        model.setCount(10);
  30.102 +        
  30.103 +        List<String> arr = model.getRepeat();
  30.104 +        assertEquals(arr.size(), 10, "Ten items: " + arr);
  30.105 +        
  30.106 +        my.mutated.clear();
  30.107 +        
  30.108 +        model.setCount(5);
  30.109 +        
  30.110 +        arr = model.getRepeat();
  30.111 +        assertEquals(arr.size(), 5, "Five items: " + arr);
  30.112 +
  30.113 +        assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
  30.114 +        assertTrue(my.mutated.contains("repeat"), "Array is in there: " + my.mutated);
  30.115 +        assertTrue(my.mutated.contains("count"), "Count is in there: " + my.mutated);
  30.116 +    }
  30.117 +    
  30.118      @Test public void derivedPropertiesAreNotified() {
  30.119          MockKnockout my = new MockKnockout();
  30.120          MockKnockout.next = my;
  30.121 @@ -61,6 +140,9 @@
  30.122          
  30.123          model.setValue(33);
  30.124          
  30.125 +        // not interested in change of this property
  30.126 +        my.mutated.remove("changedProperty");
  30.127 +        
  30.128          assertEquals(my.mutated.size(), 2, "Two properties changed: " + my.mutated);
  30.129          assertTrue(my.mutated.contains("powerValue"), "Power value is in there: " + my.mutated);
  30.130          assertTrue(my.mutated.contains("value"), "Simple value is in there: " + my.mutated);
  30.131 @@ -68,7 +150,11 @@
  30.132          my.mutated.clear();
  30.133          
  30.134          model.setUnrelated(44);
  30.135 -        assertEquals(my.mutated.size(), 1, "One property changed");
  30.136 +        
  30.137 +        
  30.138 +        // not interested in change of this property
  30.139 +        my.mutated.remove("changedProperty");
  30.140 +        assertEquals(my.mutated.size(), 1, "One property changed: " + my.mutated);
  30.141          assertTrue(my.mutated.contains("unrelated"), "Its name is unrelated");
  30.142      }
  30.143      
  30.144 @@ -92,11 +178,43 @@
  30.145          }
  30.146      }
  30.147      
  30.148 +    @OnFunction 
  30.149 +    static void doSomething() {
  30.150 +    }
  30.151 +    
  30.152      @ComputedProperty
  30.153      static int powerValue(int value) {
  30.154          return value * value;
  30.155      }
  30.156      
  30.157 +    @OnPropertyChange({ "powerValue", "unrelated" })
  30.158 +    static void aPropertyChanged(Modelik m, String name) {
  30.159 +        m.setChangedProperty(name);
  30.160 +    }
  30.161 +
  30.162 +    @OnPropertyChange({ "values" })
  30.163 +    static void anArrayPropertyChanged(String name, Modelik m) {
  30.164 +        m.setChangedProperty(name);
  30.165 +    }
  30.166 +    
  30.167 +    @Test public void changeAnything() {
  30.168 +        model.setCount(44);
  30.169 +        assertNull(model.getChangedProperty(), "No observed value change");
  30.170 +    }
  30.171 +    @Test public void changeValue() {
  30.172 +        model.setValue(33);
  30.173 +        assertEquals(model.getChangedProperty(), "powerValue", "power property changed");
  30.174 +    }
  30.175 +    @Test public void changeUnrelated() {
  30.176 +        model.setUnrelated(333);
  30.177 +        assertEquals(model.getChangedProperty(), "unrelated", "unrelated changed");
  30.178 +    }
  30.179 +
  30.180 +    @Test public void changeInArray() {
  30.181 +        model.getValues().add(10);
  30.182 +        assertEquals(model.getChangedProperty(), "values", "Something added into the array");
  30.183 +    }
  30.184 +    
  30.185      @ComputedProperty
  30.186      static String notAllowedRead() {
  30.187          return "Not allowed callback: " + leakedModel.getUnrelated();
  30.188 @@ -108,12 +226,31 @@
  30.189          return "Not allowed callback!";
  30.190      }
  30.191      
  30.192 +    @ComputedProperty
  30.193 +    static List<String> repeat(int count) {
  30.194 +        return Collections.nCopies(count, "Hello");
  30.195 +    }
  30.196 +    
  30.197      static class MockKnockout extends Knockout {
  30.198 -        List<String> mutated = new ArrayList<String>();
  30.199 +        List<String> mutated = new ArrayList<>();
  30.200 +        
  30.201 +        MockKnockout() {
  30.202 +            super(null);
  30.203 +        }
  30.204          
  30.205          @Override
  30.206          public void valueHasMutated(String prop) {
  30.207              mutated.add(prop);
  30.208          }
  30.209      }
  30.210 +    
  30.211 +    public @Test void hasPersonPropertyAndComputedFullName() {
  30.212 +        List<Person> arr = model.getPeople();
  30.213 +        assertEquals(arr.size(), 0, "By default empty");
  30.214 +        Person p = null;
  30.215 +        if (p != null) {
  30.216 +            String fullNameGenerated = p.getFullName();
  30.217 +            assertNotNull(fullNameGenerated);
  30.218 +        }
  30.219 +    }
  30.220  }
    31.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Wed Feb 27 17:50:47 2013 +0100
    31.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageController.java	Mon Oct 07 14:20:58 2013 +0200
    31.3 @@ -50,7 +50,7 @@
    31.4          if (PAGE != ref) {
    31.5              throw new IllegalStateException("Both references should be the same. " + ref + " != " + PAGE);
    31.6          }
    31.7 -        ref.PG_TITLE.setText("You want this window to be named " + ref.PG_TEXT.getValue());
    31.8 +        ref.pg_title.setText("You want this window to be named " + ref.pg_text.getValue());
    31.9      }
   31.10      
   31.11      @On(event = CLICK, id={ "pg.title", "pg.text" })
   31.12 @@ -58,6 +58,11 @@
   31.13          if (!id.equals("pg.title")) {
   31.14              throw new IllegalStateException();
   31.15          }
   31.16 -        PAGE.PG_TITLE.setText(id);
   31.17 +        PAGE.pg_title.setText(id);
   31.18 +    }
   31.19 +    
   31.20 +    @On(event = CLICK, id={ "pg.canvas" })
   31.21 +    static void clickCanvas(String id, double layerX) {
   31.22 +        PAGE.pg_canvas.setWidth((int) layerX);
   31.23      }
   31.24  }
    32.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    32.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PageTest.java	Mon Oct 07 14:20:58 2013 +0200
    32.3 @@ -0,0 +1,53 @@
    32.4 +/**
    32.5 + * Back 2 Browser Bytecode Translator
    32.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    32.7 + *
    32.8 + * This program is free software: you can redistribute it and/or modify
    32.9 + * it under the terms of the GNU General Public License as published by
   32.10 + * the Free Software Foundation, version 2 of the License.
   32.11 + *
   32.12 + * This program is distributed in the hope that it will be useful,
   32.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   32.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   32.15 + * GNU General Public License for more details.
   32.16 + *
   32.17 + * You should have received a copy of the GNU General Public License
   32.18 + * along with this program. Look for COPYING file in the top folder.
   32.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   32.20 + */
   32.21 +package org.apidesign.bck2brwsr.htmlpage;
   32.22 +
   32.23 +import java.io.IOException;
   32.24 +import java.util.Locale;
   32.25 +import javax.tools.Diagnostic;
   32.26 +import javax.tools.JavaFileObject;
   32.27 +import static org.testng.Assert.*;
   32.28 +import org.testng.annotations.Test;
   32.29 +
   32.30 +/** Verify errors emitted by the processor.
   32.31 + *
   32.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   32.33 + */
   32.34 +public class PageTest {
   32.35 +    @Test public void verifyWrongType() throws IOException {
   32.36 +        String html = "<html><body>"
   32.37 +            + "</body></html>";
   32.38 +        String code = "package x.y.z;\n"
   32.39 +            + "import org.apidesign.bck2brwsr.htmlpage.api.*;\n"
   32.40 +            + "@Page(xhtml=\"index.xhtml\", className=\"Model\", properties={\n"
   32.41 +            + "  @Property(name=\"prop\", type=Runnable.class)\n"
   32.42 +            + "})\n"
   32.43 +            + "class X {\n"
   32.44 +            + "}\n";
   32.45 +        
   32.46 +        Compile c = Compile.create(html, code);
   32.47 +        assertFalse(c.getErrors().isEmpty(), "One error: " + c.getErrors());
   32.48 +        for (Diagnostic<? extends JavaFileObject> e : c.getErrors()) {
   32.49 +            String msg = e.getMessage(Locale.ENGLISH);
   32.50 +            if (!msg.contains("Runnable")) {
   32.51 +                fail("Should contain warning about Runnable: " + msg);
   32.52 +            }
   32.53 +        }
   32.54 +    }
   32.55 +    
   32.56 +}
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/PersonImpl.java	Mon Oct 07 14:20:58 2013 +0200
    33.3 @@ -0,0 +1,62 @@
    33.4 +/**
    33.5 + * Back 2 Browser Bytecode Translator
    33.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    33.7 + *
    33.8 + * This program is free software: you can redistribute it and/or modify
    33.9 + * it under the terms of the GNU General Public License as published by
   33.10 + * the Free Software Foundation, version 2 of the License.
   33.11 + *
   33.12 + * This program is distributed in the hope that it will be useful,
   33.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   33.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   33.15 + * GNU General Public License for more details.
   33.16 + *
   33.17 + * You should have received a copy of the GNU General Public License
   33.18 + * along with this program. Look for COPYING file in the top folder.
   33.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   33.20 + */
   33.21 +package org.apidesign.bck2brwsr.htmlpage;
   33.22 +
   33.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   33.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
   33.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   33.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
   33.27 +
   33.28 +/**
   33.29 + *
   33.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   33.31 + */
   33.32 +@Model(className = "Person", properties = {
   33.33 +    @Property(name = "firstName", type = String.class),
   33.34 +    @Property(name = "lastName", type = String.class),
   33.35 +    @Property(name = "sex", type = Sex.class)
   33.36 +})
   33.37 +final class PersonImpl {
   33.38 +    @ComputedProperty 
   33.39 +    public static String fullName(String firstName, String lastName) {
   33.40 +        return firstName + " " + lastName;
   33.41 +    }
   33.42 +    
   33.43 +    @ComputedProperty
   33.44 +    public static String sexType(Sex sex) {
   33.45 +        return sex == null ? "unknown" : sex.toString();
   33.46 +    }
   33.47 +    
   33.48 +    @OnFunction
   33.49 +    static void changeSex(Person p) {
   33.50 +        if (p.getSex() == Sex.MALE) {
   33.51 +            p.setSex(Sex.FEMALE);
   33.52 +        } else {
   33.53 +            p.setSex(Sex.MALE);
   33.54 +        }
   33.55 +    }
   33.56 +    
   33.57 +    @Model(className = "People", properties = {
   33.58 +        @Property(array = true, name = "info", type = Person.class),
   33.59 +        @Property(array = true, name = "nicknames", type = String.class),
   33.60 +        @Property(array = true, name = "age", type = int.class),
   33.61 +        @Property(array = true, name = "sex", type = Sex.class)
   33.62 +    })
   33.63 +    public class PeopleImpl {
   33.64 +    }
   33.65 +}
    34.1 --- a/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Wed Feb 27 17:50:47 2013 +0100
    34.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/ProcessPageTest.java	Mon Oct 07 14:20:58 2013 +0200
    34.3 @@ -36,11 +36,12 @@
    34.4          assertNotNull(is, "Sample HTML page found");
    34.5          ProcessPage res = ProcessPage.readPage(is);
    34.6          final Set<String> ids = res.ids();
    34.7 -        assertEquals(ids.size(), 3, "Three ids found: " + ids);
    34.8 +        assertEquals(ids.size(), 4, "Four ids found: " + ids);
    34.9          
   34.10          assertEquals(res.tagNameForId("pg.title"), "title");
   34.11          assertEquals(res.tagNameForId("pg.button"), "button");
   34.12          assertEquals(res.tagNameForId("pg.text"), "input");
   34.13 +        assertEquals(res.tagNameForId("pg.canvas"), "canvas");
   34.14      }
   34.15      
   34.16      @Test public void testCompileAndRunPageController() throws Exception {
   34.17 @@ -53,11 +54,13 @@
   34.18              + "doc.title.innerHTML = 'nothing';\n"
   34.19              + "doc.text = new Object();\n"
   34.20              + "doc.text.value = 'something';\n"
   34.21 +            + "doc.canvas = new Object();\n"
   34.22              + "doc.getElementById = function(id) {\n"
   34.23              + "    switch(id) {\n"
   34.24              + "      case 'pg.button': return doc.button;\n"
   34.25              + "      case 'pg.title': return doc.title;\n"
   34.26              + "      case 'pg.text': return doc.text;\n"
   34.27 +            + "      case 'pg.canvas': return doc.canvas;\n"
   34.28              + "    }\n"
   34.29              + "    throw id;\n"
   34.30              + "  }\n"
   34.31 @@ -92,11 +95,13 @@
   34.32              + "doc.title.innerHTML = 'nothing';\n"
   34.33              + "doc.text = new Object();\n"
   34.34              + "doc.text.value = 'something';\n"
   34.35 +            + "doc.canvas = new Object();\n"
   34.36              + "doc.getElementById = function(id) {\n"
   34.37              + "    switch(id) {\n"
   34.38              + "      case 'pg.button': return doc.button;\n"
   34.39              + "      case 'pg.title': return doc.title;\n"
   34.40              + "      case 'pg.text': return doc.text;\n"
   34.41 +            + "      case 'pg.canvas': return doc.canvas;\n"
   34.42              + "    }\n"
   34.43              + "    throw id;\n"
   34.44              + "  }\n"
   34.45 @@ -123,12 +128,61 @@
   34.46          assertEquals(ret, "pg.title", "Title has been passed to the method argument");
   34.47      }
   34.48  
   34.49 +    @Test public void clickWithArgumentAndParameterCalled() throws Exception {
   34.50 +        StringBuilder sb = new StringBuilder();
   34.51 +        sb.append(
   34.52 +              "var window = new Object();\n"
   34.53 +            + "var doc = new Object();\n"
   34.54 +            + "var eventObject = new Object();\n"
   34.55 +            + "eventObject.layerX = 100;\n"
   34.56 +            + "doc.button = new Object();\n"
   34.57 +            + "doc.title = new Object();\n"
   34.58 +            + "doc.title.innerHTML = 'nothing';\n"
   34.59 +            + "doc.text = new Object();\n"
   34.60 +            + "doc.text.value = 'something';\n"
   34.61 +            + "doc.canvas = new Object();\n"
   34.62 +            + "doc.canvas.width = 200;\n"                
   34.63 +            + "doc.getElementById = function(id) {\n"
   34.64 +            + "    switch(id) {\n"
   34.65 +            + "      case 'pg.button': return doc.button;\n"
   34.66 +            + "      case 'pg.title': return doc.title;\n"
   34.67 +            + "      case 'pg.text': return doc.text;\n"
   34.68 +            + "      case 'pg.canvas': return doc.canvas;\n"
   34.69 +            + "    }\n"
   34.70 +            + "    throw id;\n"
   34.71 +            + "  }\n"
   34.72 +            + "\n"
   34.73 +            + "function clickAndCheck() {\n"
   34.74 +            + "  doc.canvas.onclick(eventObject);\n"
   34.75 +            + "  return doc.canvas.width.toString();\n"
   34.76 +            + "};\n"
   34.77 +            + "\n"
   34.78 +            + "window.document = doc;\n"
   34.79 +        );
   34.80 +        Invocable i = compileClass(sb, 
   34.81 +            "org/apidesign/bck2brwsr/htmlpage/PageController"
   34.82 +        );
   34.83 +
   34.84 +        Object ret = null;
   34.85 +        try {
   34.86 +            ret = i.invokeFunction("clickAndCheck");
   34.87 +        } catch (ScriptException ex) {
   34.88 +            fail("Execution failed in " + sb, ex);
   34.89 +        } catch (NoSuchMethodException ex) {
   34.90 +            fail("Cannot find method in " + sb, ex);
   34.91 +        }
   34.92 +       assertEquals(ret, "100", "layerX has been passed to the method argument");
   34.93 +    }
   34.94 +    
   34.95      static Invocable compileClass(StringBuilder sb, String... names) throws ScriptException, IOException {
   34.96          if (sb == null) {
   34.97              sb = new StringBuilder();
   34.98          }
   34.99          Bck2Brwsr.generate(sb, ProcessPageTest.class.getClassLoader(), names);
  34.100          sb.append("var vm = this.bck2brwsr();\n");
  34.101 +        for (String c : names) {
  34.102 +            sb.append("vm.loadClass('").append(c.replace('/', '.')).append("');\n");
  34.103 +        }
  34.104          
  34.105          ScriptEngineManager sem = new ScriptEngineManager();
  34.106          ScriptEngine js = sem.getEngineByExtension("js");
    35.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    35.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/Sex.java	Mon Oct 07 14:20:58 2013 +0200
    35.3 @@ -0,0 +1,26 @@
    35.4 +/**
    35.5 + * Back 2 Browser Bytecode Translator
    35.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    35.7 + *
    35.8 + * This program is free software: you can redistribute it and/or modify
    35.9 + * it under the terms of the GNU General Public License as published by
   35.10 + * the Free Software Foundation, version 2 of the License.
   35.11 + *
   35.12 + * This program is distributed in the hope that it will be useful,
   35.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   35.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   35.15 + * GNU General Public License for more details.
   35.16 + *
   35.17 + * You should have received a copy of the GNU General Public License
   35.18 + * along with this program. Look for COPYING file in the top folder.
   35.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   35.20 + */
   35.21 +package org.apidesign.bck2brwsr.htmlpage;
   35.22 +
   35.23 +/**
   35.24 + *
   35.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   35.26 + */
   35.27 +public enum Sex {
   35.28 +    MALE, FEMALE;
   35.29 +}
    36.1 --- a/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html	Wed Feb 27 17:50:47 2013 +0100
    36.2 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/TestPage.html	Mon Oct 07 14:20:58 2013 +0200
    36.3 @@ -26,5 +26,6 @@
    36.4      <body>
    36.5          New title: <input id="pg.text"/>
    36.6          <button id="pg.button">Change title!</button>
    36.7 +        <canvas id="pg.canvas" width="100"/>
    36.8      </body>
    36.9  </html>
    37.1 --- a/javaquery/demo-calculator-dynamic/nbactions.xml	Wed Feb 27 17:50:47 2013 +0100
    37.2 +++ b/javaquery/demo-calculator-dynamic/nbactions.xml	Mon Oct 07 14:20:58 2013 +0200
    37.3 @@ -23,7 +23,7 @@
    37.4              <actionName>run</actionName>
    37.5              <goals>
    37.6                  <goal>process-classes</goal>
    37.7 -                <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
    37.8 +                <goal>bck2brwsr:brwsr</goal>
    37.9              </goals>
   37.10          </action>
   37.11      </actions>
    38.1 --- a/javaquery/demo-calculator-dynamic/pom.xml	Wed Feb 27 17:50:47 2013 +0100
    38.2 +++ b/javaquery/demo-calculator-dynamic/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    38.3 @@ -1,11 +1,10 @@
    38.4  <?xml version="1.0"?>
    38.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    38.6 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    38.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    38.8    <modelVersion>4.0.0</modelVersion>
    38.9  
   38.10    <groupId>org.apidesign.bck2brwsr</groupId>
   38.11    <artifactId>demo.calculator</artifactId>
   38.12 -  <version>0.3-SNAPSHOT</version>
   38.13 +  <version>0.9-SNAPSHOT</version>
   38.14    <packaging>jar</packaging>
   38.15  
   38.16    <name>JavaQuery Demo - Calculator</name>
   38.17 @@ -18,8 +17,8 @@
   38.18        <plugins>
   38.19              <plugin>
   38.20                  <groupId>org.apidesign.bck2brwsr</groupId>
   38.21 -                <artifactId>mojo</artifactId>
   38.22 -                <version>0.3-SNAPSHOT</version>
   38.23 +                <artifactId>bck2brwsr-maven-plugin</artifactId>
   38.24 +                <version>${project.version}</version>
   38.25                  <executions>
   38.26                      <execution>
   38.27                          <goals>
   38.28 @@ -62,6 +61,14 @@
   38.29             </configuration>
   38.30           </plugin>
   38.31           <plugin>
   38.32 +           <groupId>org.apache.maven.plugins</groupId>
   38.33 +           <artifactId>maven-javadoc-plugin</artifactId>
   38.34 +           <version>2.9</version>
   38.35 +           <configuration>
   38.36 +             <skip>true</skip>
   38.37 +           </configuration>
   38.38 +         </plugin>
   38.39 +         <plugin>
   38.40              <artifactId>maven-assembly-plugin</artifactId>
   38.41                  <version>2.4</version>
   38.42                  <executions>
   38.43 @@ -86,13 +93,13 @@
   38.44      <dependency>
   38.45        <groupId>org.apidesign.bck2brwsr</groupId>
   38.46        <artifactId>emul</artifactId>
   38.47 -      <version>0.3-SNAPSHOT</version>
   38.48 +      <version>${project.version}</version>
   38.49        <classifier>rt</classifier>
   38.50      </dependency>
   38.51      <dependency>
   38.52        <groupId>org.apidesign.bck2brwsr</groupId>
   38.53        <artifactId>javaquery.api</artifactId>
   38.54 -      <version>0.3-SNAPSHOT</version>
   38.55 +      <version>${project.version}</version>
   38.56      </dependency>
   38.57      <dependency>
   38.58        <groupId>org.testng</groupId>
   38.59 @@ -105,7 +112,7 @@
   38.60        <artifactId>vm4brwsr</artifactId>
   38.61        <classifier>js</classifier>
   38.62        <type>zip</type>
   38.63 -      <version>0.3-SNAPSHOT</version>
   38.64 +      <version>${project.version}</version>
   38.65        <scope>provided</scope>
   38.66      </dependency>
   38.67    </dependencies>
    39.1 --- a/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java	Wed Feb 27 17:50:47 2013 +0100
    39.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/Calc.java	Mon Oct 07 14:20:58 2013 +0200
    39.3 @@ -17,9 +17,11 @@
    39.4   */
    39.5  package org.apidesign.bck2brwsr.demo.calc;
    39.6  
    39.7 +import java.util.List;
    39.8  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
    39.9  import org.apidesign.bck2brwsr.htmlpage.api.On;
   39.10  import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   39.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   39.12  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   39.13  import org.apidesign.bck2brwsr.htmlpage.api.Property;
   39.14  
   39.15 @@ -33,11 +35,12 @@
   39.16      @Property(name = "memory", type = double.class),
   39.17      @Property(name = "display", type = double.class),
   39.18      @Property(name = "operation", type = String.class),
   39.19 -    @Property(name = "hover", type = boolean.class)
   39.20 +    @Property(name = "hover", type = boolean.class),
   39.21 +    @Property(name = "history", type = HistoryImpl.class, array = true)
   39.22  })
   39.23  public class Calc {
   39.24      static {
   39.25 -        new Calculator().applyBindings();
   39.26 +        new Calculator().applyBindings().setOperation("plus");
   39.27      }
   39.28      
   39.29      @On(event = CLICK, id="clear")
   39.30 @@ -48,31 +51,48 @@
   39.31      }
   39.32      
   39.33      @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
   39.34 -    static void applyOp(Calculator c, String op) {
   39.35 +    static void applyOp(Calculator c, String id) {
   39.36          c.setMemory(c.getDisplay());
   39.37 -        c.setOperation(op);
   39.38 +        c.setOperation(id);
   39.39          c.setDisplay(0);
   39.40      }
   39.41  
   39.42      @On(event = MOUSE_OVER, id= { "result" })
   39.43 -    static void attemptingIn(Calculator c, String op) {
   39.44 +    static void attemptingIn(Calculator c) {
   39.45          c.setHover(true);
   39.46      }
   39.47      @On(event = MOUSE_OUT, id= { "result" })
   39.48 -    static void attemptingOut(Calculator c, String op) {
   39.49 +    static void attemptingOut(Calculator c) {
   39.50          c.setHover(false);
   39.51      }
   39.52      
   39.53      @On(event = CLICK, id="result")
   39.54      static void computeTheValue(Calculator c) {
   39.55 -        c.setDisplay(compute(
   39.56 +        final double newValue = compute(
   39.57              c.getOperation(), 
   39.58              c.getMemory(), 
   39.59              c.getDisplay()
   39.60 -        ));
   39.61 +        );
   39.62 +        c.setDisplay(newValue);
   39.63 +        if (!containsValue(c.getHistory(), newValue)) {
   39.64 +            History h = new History();
   39.65 +            h.setValue(newValue);
   39.66 +            h.setOperation(c.getOperation());
   39.67 +            c.getHistory().add(h);
   39.68 +        }
   39.69          c.setMemory(0);
   39.70      }
   39.71      
   39.72 +    @OnFunction
   39.73 +    static void recoverMemory(Calculator c, History data) {
   39.74 +        c.setDisplay(data.getValue());
   39.75 +    }
   39.76 +
   39.77 +    @OnFunction
   39.78 +    static void removeMemory(Calculator c, History data) {
   39.79 +        c.getHistory().remove(data);
   39.80 +    }
   39.81 +    
   39.82      private static double compute(String op, double memory, double display) {
   39.83          switch (op) {
   39.84              case "plus": return memory + display;
   39.85 @@ -84,18 +104,18 @@
   39.86      }
   39.87      
   39.88      @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
   39.89 -    static void addDigit(String digit, Calculator c) {
   39.90 -        digit = digit.substring(1);
   39.91 +    static void addDigit(String id, Calculator c) {
   39.92 +        id = id.substring(1);
   39.93          
   39.94          double v = c.getDisplay();
   39.95          if (v == 0.0) {
   39.96 -            c.setDisplay(Integer.parseInt(digit));
   39.97 +            c.setDisplay(Integer.parseInt(id));
   39.98          } else {
   39.99              String txt = Double.toString(v);
  39.100              if (txt.endsWith(".0")) {
  39.101                  txt = txt.substring(0, txt.length() - 2);
  39.102              }
  39.103 -            txt = txt + digit;
  39.104 +            txt = txt + id;
  39.105              c.setDisplay(Double.parseDouble(txt));
  39.106          }
  39.107      }
  39.108 @@ -109,4 +129,18 @@
  39.109          }
  39.110          return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
  39.111      }
  39.112 +    
  39.113 +    @ComputedProperty
  39.114 +    static boolean emptyHistory(List<?> history) {
  39.115 +        return history.isEmpty();
  39.116 +    }
  39.117 +
  39.118 +    private static boolean containsValue(List<History> arr, final double newValue) {
  39.119 +        for (History history : arr) {
  39.120 +            if (history.getValue() == newValue) {
  39.121 +                return true;
  39.122 +            }
  39.123 +        }
  39.124 +        return false;
  39.125 +    }
  39.126  }
    40.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    40.2 +++ b/javaquery/demo-calculator-dynamic/src/main/java/org/apidesign/bck2brwsr/demo/calc/HistoryImpl.java	Mon Oct 07 14:20:58 2013 +0200
    40.3 @@ -0,0 +1,43 @@
    40.4 +/**
    40.5 + * Back 2 Browser Bytecode Translator
    40.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    40.7 + *
    40.8 + * This program is free software: you can redistribute it and/or modify
    40.9 + * it under the terms of the GNU General Public License as published by
   40.10 + * the Free Software Foundation, version 2 of the License.
   40.11 + *
   40.12 + * This program is distributed in the hope that it will be useful,
   40.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   40.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   40.15 + * GNU General Public License for more details.
   40.16 + *
   40.17 + * You should have received a copy of the GNU General Public License
   40.18 + * along with this program. Look for COPYING file in the top folder.
   40.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   40.20 + */
   40.21 +package org.apidesign.bck2brwsr.demo.calc;
   40.22 +
   40.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   40.24 +import org.apidesign.bck2brwsr.htmlpage.api.Model;
   40.25 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   40.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
   40.27 +
   40.28 +/**
   40.29 + *
   40.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   40.31 + */
   40.32 +@Model(className = "History", properties = {
   40.33 +    @Property(name = "value", type = double.class),
   40.34 +    @Property(name = "operation", type = String.class)
   40.35 +})
   40.36 +public class HistoryImpl {
   40.37 +    @ComputedProperty
   40.38 +    static String resultOf(String operation) {
   40.39 +        return "result of " + operation;
   40.40 +    }
   40.41 +    
   40.42 +    @OnFunction
   40.43 +    static void twice(History data) {
   40.44 +        data.setValue(2.0 * data.getValue());
   40.45 +    }
   40.46 +}
    41.1 --- a/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml	Wed Feb 27 17:50:47 2013 +0100
    41.2 +++ b/javaquery/demo-calculator-dynamic/src/main/resources/org/apidesign/bck2brwsr/demo/calc/Calculator.xhtml	Mon Oct 07 14:20:58 2013 +0200
    41.3 @@ -78,82 +78,25 @@
    41.4          </table>
    41.5          <div data-bind="text: displayPreview"></div>
    41.6          
    41.7 +        <h4>Previous Results</h4>
    41.8 +        
    41.9 +        <div data-bind="if: emptyHistory">No results yet.</div>
   41.10 +        <ul data-bind="foreach: history">
   41.11 +            <li>
   41.12 +                <span data-bind="text: $data.value"></span> -
   41.13 +                <a href="#" data-bind="click: $root.recoverMemory">Use</a>
   41.14 +                <a href="#" data-bind="click: $root.removeMemory">Remove</a>
   41.15 +                <a href="#" data-bind="click: $data.twice">Double</a> -
   41.16 +                <span data-bind="text: $data.resultOf"></span>
   41.17 +            </li>
   41.18 +        </ul>
   41.19 +        
   41.20          <script src="bck2brwsr.js"></script>
   41.21          <script type="text/javascript">
   41.22 -            var vm = bck2brwsr('demo.calculator-0.3-SNAPSHOT.jar');
   41.23 +            var vm = bck2brwsr('demo.calculator-0.6.jar');
   41.24              vm.loadClass('org.apidesign.bck2brwsr.demo.calc.Calc');
   41.25          </script>
   41.26          
   41.27          <hr/>
   41.28 -    <pre>
   41.29 -    <span class="keyword-directive">package</span> org.apidesign.bck2brwsr.mavenhtml;
   41.30 -
   41.31 -    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.OnClick;
   41.32 -    <span class="keyword-directive">import</span> org.apidesign.bck2brwsr.htmlpage.api.Page;
   41.33 -
   41.34 -    <span class="comment">/**</span> <span class="comment">HTML5</span><span class="comment"> &amp; </span><span class="comment">Java</span> <span class="comment">demo</span> <span class="comment">showing</span> <span class="comment">the</span> <span class="comment">power</span> <span class="comment">of</span> <a href="http://wiki.apidesign.org/wiki/AnnotationProcessor">annotation processors</a>
   41.35 -    <span class="comment"> * </span><span class="comment">as</span> <span class="comment">well</span> <span class="comment">as</span> <span class="comment">other</span> <span class="comment">goodies</span><span class="comment">, including type-safe association between</span>
   41.36 -    <span class="comment"> * </span><span class="comment">an XHTML page and Java.</span>
   41.37 -    <span class="comment"> * </span>
   41.38 -    <span class="comment"> * </span><span class="ST1">@author</span> <span class="comment">Jaroslav</span> <span class="comment">Tulach</span> <span class="ST0">&lt;jaroslav.tulach@apidesign.org&gt;</span>
   41.39 -     <span class="comment">*/</span>
   41.40 -    @Page(xhtml=<span class="string">&quot;</span><span class="string">Calculator.xhtml</span><span class="string">&quot;</span>)
   41.41 -    <span class="keyword-directive">public</span> <span class="keyword-directive">class</span> App {
   41.42 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> memory;
   41.43 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> String operation;
   41.44 -
   41.45 -        @OnClick(id=<span class="string">&quot;</span><span class="string">clear</span><span class="string">&quot;</span>)
   41.46 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> clear() {
   41.47 -            memory = <span class="number">0</span>;
   41.48 -            operation = <span class="keyword-directive">null</span>;
   41.49 -            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   41.50 -        }
   41.51 -
   41.52 -        @OnClick(id= { <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span> })
   41.53 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> applyOp(String op) {
   41.54 -            memory = getValue();
   41.55 -            operation = op;
   41.56 -            Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">0</span><span class="string">&quot;</span>);
   41.57 -        }
   41.58 -
   41.59 -        @OnClick(id=<span class="string">&quot;</span><span class="string">result</span><span class="string">&quot;</span>)
   41.60 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> computeTheValue() {
   41.61 -            <span class="keyword-directive">switch</span> (operation) {
   41.62 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">plus</span><span class="string">&quot;</span>: setValue(memory + getValue()); <span class="keyword-directive">break</span>;
   41.63 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">minus</span><span class="string">&quot;</span>: setValue(memory - getValue()); <span class="keyword-directive">break</span>;
   41.64 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">mul</span><span class="string">&quot;</span>: setValue(memory * getValue()); <span class="keyword-directive">break</span>;
   41.65 -                <span class="keyword-directive">case</span> <span class="string">&quot;</span><span class="string">div</span><span class="string">&quot;</span>: setValue(memory / getValue()); <span class="keyword-directive">break</span>;
   41.66 -                <span class="keyword-directive">default</span>: <span class="keyword-directive">throw</span> <span class="keyword-directive">new</span> IllegalStateException(operation);
   41.67 -            }
   41.68 -        }
   41.69 -
   41.70 -        @OnClick(id={<span class="string">&quot;</span><span class="string">n0</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n1</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n2</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n3</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n4</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n5</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n6</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n7</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n8</span><span class="string">&quot;</span>, <span class="string">&quot;</span><span class="string">n9</span><span class="string">&quot;</span>}) 
   41.71 -        <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> addDigit(String digit) {
   41.72 -            digit = digit.substring(<span class="number">1</span>);
   41.73 -            String v = Calculator.DISPLAY.getValue();
   41.74 -            <span class="keyword-directive">if</span> (getValue() == <span class="number">0.0</span>) {
   41.75 -                Calculator.DISPLAY.setValue(digit);
   41.76 -            } <span class="keyword-directive">else</span> {
   41.77 -                Calculator.DISPLAY.setValue(v + digit);
   41.78 -            }
   41.79 -        }
   41.80 -
   41.81 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">void</span> setValue(<span class="keyword-directive">double</span> v) {
   41.82 -            StringBuilder sb = <span class="keyword-directive">new</span> StringBuilder();
   41.83 -            sb.append(v);
   41.84 -            Calculator.DISPLAY.setValue(sb.toString());
   41.85 -        }
   41.86 -
   41.87 -        <span class="keyword-directive">private</span> <span class="keyword-directive">static</span> <span class="keyword-directive">double</span> getValue() {
   41.88 -            <span class="keyword-directive">try</span> {
   41.89 -                <span class="keyword-directive">return</span> Double.parseDouble(Calculator.DISPLAY.getValue());
   41.90 -            } <span class="keyword-directive">catch</span> (NumberFormatException ex) {
   41.91 -                Calculator.DISPLAY.setValue(<span class="string">&quot;</span><span class="string">err</span><span class="string">&quot;</span>);
   41.92 -                <span class="keyword-directive">return</span> <span class="number">0.0</span>;
   41.93 -            }
   41.94 -        }
   41.95 -    }
   41.96 -
   41.97 -    </pre>
   41.98      </body>
   41.99  </html>
    42.1 --- a/javaquery/demo-calculator/nbactions.xml	Wed Feb 27 17:50:47 2013 +0100
    42.2 +++ b/javaquery/demo-calculator/nbactions.xml	Mon Oct 07 14:20:58 2013 +0200
    42.3 @@ -23,7 +23,7 @@
    42.4              <actionName>run</actionName>
    42.5              <goals>
    42.6                  <goal>package</goal>
    42.7 -                <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
    42.8 +                <goal>bck2brwsr:brwsr</goal>
    42.9              </goals>
   42.10              <properties>
   42.11                  <skipTests>true</skipTests>
    43.1 --- a/javaquery/demo-calculator/pom.xml	Wed Feb 27 17:50:47 2013 +0100
    43.2 +++ b/javaquery/demo-calculator/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    43.3 @@ -1,11 +1,10 @@
    43.4  <?xml version="1.0"?>
    43.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    43.6 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    43.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    43.8    <modelVersion>4.0.0</modelVersion>
    43.9  
   43.10    <groupId>org.apidesign.bck2brwsr</groupId>
   43.11    <artifactId>demo.static.calculator</artifactId>
   43.12 -  <version>0.3-SNAPSHOT</version>
   43.13 +  <version>0.9-SNAPSHOT</version>
   43.14    <packaging>jar</packaging>
   43.15  
   43.16    <name>JavaQuery Demo - Calculator - Static Compilation</name>
   43.17 @@ -13,16 +12,18 @@
   43.18  
   43.19    <properties>
   43.20      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   43.21 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
   43.22    </properties>
   43.23    <build>
   43.24        <plugins>
   43.25              <plugin>
   43.26                  <groupId>org.apidesign.bck2brwsr</groupId>
   43.27 -                <artifactId>mojo</artifactId>
   43.28 -                <version>0.3-SNAPSHOT</version>
   43.29 +                <artifactId>bck2brwsr-maven-plugin</artifactId>
   43.30 +                <version>${project.version}</version>
   43.31                  <executions>
   43.32                      <execution>
   43.33                          <goals>
   43.34 +                            <goal>j2js</goal>
   43.35                              <goal>brwsr</goal>
   43.36                          </goals>
   43.37                      </execution>
   43.38 @@ -30,6 +31,8 @@
   43.39                  <configuration>
   43.40                      <directory>${project.build.directory}/${project.build.finalName}-bck2brwsr/public_html/</directory>
   43.41                      <startpage>index.xhtml</startpage>
   43.42 +                    <javascript>${project.build.directory}/bck2brwsr.js</javascript>
   43.43 +                    <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
   43.44                  </configuration>
   43.45              </plugin>
   43.46           <plugin>
   43.47 @@ -80,6 +83,14 @@
   43.48               <skip>true</skip>
   43.49             </configuration>
   43.50           </plugin>      
   43.51 +         <plugin>
   43.52 +           <groupId>org.apache.maven.plugins</groupId>
   43.53 +           <artifactId>maven-javadoc-plugin</artifactId>
   43.54 +           <version>2.9</version>
   43.55 +           <configuration>
   43.56 +             <skip>true</skip>
   43.57 +           </configuration>
   43.58 +         </plugin>
   43.59        </plugins>
   43.60    </build>
   43.61  
   43.62 @@ -87,21 +98,13 @@
   43.63      <dependency>
   43.64        <groupId>org.apidesign.bck2brwsr</groupId>
   43.65        <artifactId>emul</artifactId>
   43.66 -      <version>0.3-SNAPSHOT</version>
   43.67 +      <version>${project.version}</version>
   43.68        <classifier>rt</classifier>
   43.69      </dependency>
   43.70      <dependency>
   43.71        <groupId>org.apidesign.bck2brwsr</groupId>
   43.72        <artifactId>javaquery.api</artifactId>
   43.73 -      <version>0.3-SNAPSHOT</version>
   43.74 -    </dependency>
   43.75 -    <dependency>
   43.76 -      <groupId>org.apidesign.bck2brwsr</groupId>
   43.77 -      <artifactId>vm4brwsr</artifactId>
   43.78 -      <classifier>js</classifier>
   43.79 -      <type>zip</type>
   43.80 -      <version>0.3-SNAPSHOT</version>
   43.81 -      <scope>provided</scope>
   43.82 +      <version>${project.version}</version>
   43.83      </dependency>
   43.84    </dependencies>
   43.85  </project>
    44.1 --- a/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml	Wed Feb 27 17:50:47 2013 +0100
    44.2 +++ b/javaquery/demo-calculator/src/main/assembly/bck2brwsr.xml	Mon Oct 07 14:20:58 2013 +0200
    44.3 @@ -37,15 +37,6 @@
    44.4              <include>*:rt</include>
    44.5          </includes>
    44.6      </dependencySet>
    44.7 -    <dependencySet>
    44.8 -        <useProjectArtifact>false</useProjectArtifact>
    44.9 -        <scope>provided</scope>
   44.10 -        <includes>
   44.11 -            <include>*:js</include>
   44.12 -        </includes>
   44.13 -        <unpack>true</unpack>
   44.14 -        <outputDirectory>/</outputDirectory>
   44.15 -    </dependencySet>
   44.16    </dependencySets> 
   44.17    <files>
   44.18      <file>
   44.19 @@ -53,6 +44,10 @@
   44.20        <outputDirectory>/</outputDirectory>
   44.21      </file>
   44.22      <file>
   44.23 +      <source>${project.build.directory}/bck2brwsr.js</source>
   44.24 +      <outputDirectory>/</outputDirectory>
   44.25 +    </file>
   44.26 +    <file>
   44.27        <source>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml</source>
   44.28        <outputDirectory>/</outputDirectory>
   44.29        <destName>index.xhtml</destName>
    45.1 --- a/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java	Wed Feb 27 17:50:47 2013 +0100
    45.2 +++ b/javaquery/demo-calculator/src/main/java/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calc.java	Mon Oct 07 14:20:58 2013 +0200
    45.3 @@ -17,9 +17,11 @@
    45.4   */
    45.5  package org.apidesign.bck2brwsr.demo.calc.staticcompilation;
    45.6  
    45.7 +import java.util.List;
    45.8  import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
    45.9  import org.apidesign.bck2brwsr.htmlpage.api.On;
   45.10  import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   45.11 +import org.apidesign.bck2brwsr.htmlpage.api.OnFunction;
   45.12  import org.apidesign.bck2brwsr.htmlpage.api.Page;
   45.13  import org.apidesign.bck2brwsr.htmlpage.api.Property;
   45.14  
   45.15 @@ -33,11 +35,12 @@
   45.16      @Property(name = "memory", type = double.class),
   45.17      @Property(name = "display", type = double.class),
   45.18      @Property(name = "operation", type = String.class),
   45.19 -    @Property(name = "hover", type = boolean.class)
   45.20 +    @Property(name = "hover", type = boolean.class),
   45.21 +    @Property(name = "history", type = double.class, array = true)
   45.22  })
   45.23  public class Calc {
   45.24      static {
   45.25 -        new Calculator().applyBindings();
   45.26 +        new Calculator().applyBindings().setOperation("plus");
   45.27      }
   45.28      
   45.29      @On(event = CLICK, id="clear")
   45.30 @@ -48,31 +51,45 @@
   45.31      }
   45.32      
   45.33      @On(event = CLICK, id= { "plus", "minus", "mul", "div" })
   45.34 -    static void applyOp(Calculator c, String op) {
   45.35 +    static void applyOp(Calculator c, String id) {
   45.36          c.setMemory(c.getDisplay());
   45.37 -        c.setOperation(op);
   45.38 +        c.setOperation(id);
   45.39          c.setDisplay(0);
   45.40      }
   45.41  
   45.42      @On(event = MOUSE_OVER, id= { "result" })
   45.43 -    static void attemptingIn(Calculator c, String op) {
   45.44 +    static void attemptingIn(Calculator c) {
   45.45          c.setHover(true);
   45.46      }
   45.47      @On(event = MOUSE_OUT, id= { "result" })
   45.48 -    static void attemptingOut(Calculator c, String op) {
   45.49 +    static void attemptingOut(Calculator c) {
   45.50          c.setHover(false);
   45.51      }
   45.52      
   45.53      @On(event = CLICK, id="result")
   45.54      static void computeTheValue(Calculator c) {
   45.55 -        c.setDisplay(compute(
   45.56 +        final double newValue = compute(
   45.57              c.getOperation(), 
   45.58              c.getMemory(), 
   45.59              c.getDisplay()
   45.60 -        ));
   45.61 +        );
   45.62 +        c.setDisplay(newValue);
   45.63 +        if (!c.getHistory().contains(newValue)) {
   45.64 +            c.getHistory().add(newValue);
   45.65 +        }
   45.66          c.setMemory(0);
   45.67      }
   45.68      
   45.69 +    @OnFunction
   45.70 +    static void recoverMemory(Calculator c, double data) {
   45.71 +        c.setDisplay(data);
   45.72 +    }
   45.73 +
   45.74 +    @OnFunction
   45.75 +    static void removeMemory(Calculator c, double data) {
   45.76 +        c.getHistory().remove(data);
   45.77 +    }
   45.78 +    
   45.79      private static double compute(String op, double memory, double display) {
   45.80          switch (op) {
   45.81              case "plus": return memory + display;
   45.82 @@ -84,18 +101,18 @@
   45.83      }
   45.84      
   45.85      @On(event = CLICK, id={"n0", "n1", "n2", "n3", "n4", "n5", "n6", "n7", "n8", "n9"}) 
   45.86 -    static void addDigit(String digit, Calculator c) {
   45.87 -        digit = digit.substring(1);
   45.88 +    static void addDigit(String id, Calculator c) {
   45.89 +        id = id.substring(1);
   45.90          
   45.91          double v = c.getDisplay();
   45.92          if (v == 0.0) {
   45.93 -            c.setDisplay(Integer.parseInt(digit));
   45.94 +            c.setDisplay(Integer.parseInt(id));
   45.95          } else {
   45.96              String txt = Double.toString(v);
   45.97              if (txt.endsWith(".0")) {
   45.98                  txt = txt.substring(0, txt.length() - 2);
   45.99              }
  45.100 -            txt = txt + digit;
  45.101 +            txt = txt + id;
  45.102              c.setDisplay(Double.parseDouble(txt));
  45.103          }
  45.104      }
  45.105 @@ -109,4 +126,9 @@
  45.106          }
  45.107          return "Attempt to compute " + memory + " " + operation + " " + display + " = " + compute(operation, memory, display);
  45.108      }
  45.109 +    
  45.110 +    @ComputedProperty
  45.111 +    static boolean emptyHistory(List<?> history) {
  45.112 +        return history.isEmpty();
  45.113 +    }
  45.114  }
    46.1 --- a/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Wed Feb 27 17:50:47 2013 +0100
    46.2 +++ b/javaquery/demo-calculator/src/main/resources/org/apidesign/bck2brwsr/demo/calc/staticcompilation/Calculator.xhtml	Mon Oct 07 14:20:58 2013 +0200
    46.3 @@ -76,10 +76,22 @@
    46.4                  </tr>
    46.5              </tbody>
    46.6          </table>
    46.7 +        
    46.8 +        <h4>Previous Results</h4>
    46.9 +        
   46.10 +        <div data-bind="if: emptyHistory">No results yet.</div>
   46.11 +        <ul data-bind="foreach: history">
   46.12 +            <li>
   46.13 +                <span data-bind="text: $data"></span> -
   46.14 +                <a href="#" data-bind="click: $root.recoverMemory">Use</a>
   46.15 +                <a href="#" data-bind="click: $root.removeMemory">Remove</a>
   46.16 +            </li>
   46.17 +        </ul>
   46.18 +        
   46.19          <div data-bind="text: displayPreview"></div>
   46.20 -        <script src="bck2brwsr.js"/>
   46.21 +        <script src="bck2brwsr.js"></script>
   46.22          <script>
   46.23 -            var vm = bck2brwsr('demo.static.calculator-0.3-SNAPSHOT.jar');
   46.24 +            var vm = bck2brwsr('demo.static.calculator-0.6.jar');
   46.25              vm.loadClass('org.apidesign.bck2brwsr.demo.calc.staticcompilation.Calc');
   46.26          </script>
   46.27      </body>
    47.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    47.2 +++ b/javaquery/demo-twitter/bck2brwsr-assembly.xml	Mon Oct 07 14:20:58 2013 +0200
    47.3 @@ -0,0 +1,62 @@
    47.4 +<?xml version="1.0"?>
    47.5 +<!--
    47.6 +
    47.7 +    Back 2 Browser Bytecode Translator
    47.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    47.9 +
   47.10 +    This program is free software: you can redistribute it and/or modify
   47.11 +    it under the terms of the GNU General Public License as published by
   47.12 +    the Free Software Foundation, version 2 of the License.
   47.13 +
   47.14 +    This program is distributed in the hope that it will be useful,
   47.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   47.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   47.17 +    GNU General Public License for more details.
   47.18 +
   47.19 +    You should have received a copy of the GNU General Public License
   47.20 +    along with this program. Look for COPYING file in the top folder.
   47.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   47.22 +
   47.23 +-->
   47.24 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   47.25 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
   47.26 +  
   47.27 +  <id>bck2brwsr</id>
   47.28 +  <formats>
   47.29 +      <format>zip</format>
   47.30 +  </formats>
   47.31 +  <baseDirectory>public_html</baseDirectory>
   47.32 +  <dependencySets>
   47.33 +    <dependencySet>
   47.34 +        <useProjectArtifact>false</useProjectArtifact>
   47.35 +        <scope>runtime</scope>
   47.36 +        <outputDirectory>lib</outputDirectory>
   47.37 +        <includes>
   47.38 +            <include>*:jar</include>
   47.39 +            <include>*:rt</include>
   47.40 +        </includes>
   47.41 +    </dependencySet>
   47.42 +  </dependencySets> 
   47.43 +  <fileSets>
   47.44 +      <fileSet>
   47.45 +          <directory>${project.build.directory}/classes/org/apidesign/bck2brwsr/demo/twitter/</directory>
   47.46 +          <includes>
   47.47 +              <include>**/*</include>
   47.48 +          </includes>
   47.49 +          <excludes>
   47.50 +              <exclude>**/*.class</exclude>
   47.51 +          </excludes>
   47.52 +          <outputDirectory>/</outputDirectory>
   47.53 +      </fileSet>
   47.54 +  </fileSets>
   47.55 +  <files>
   47.56 +    <file>
   47.57 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   47.58 +      <outputDirectory>/</outputDirectory>
   47.59 +    </file>
   47.60 +    <file>
   47.61 +      <source>${project.build.directory}/bck2brwsr.js</source>
   47.62 +      <outputDirectory>/</outputDirectory>
   47.63 +    </file>
   47.64 +  </files>
   47.65 +</assembly>
   47.66 \ No newline at end of file
    48.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    48.2 +++ b/javaquery/demo-twitter/nb-configuration.xml	Mon Oct 07 14:20:58 2013 +0200
    48.3 @@ -0,0 +1,37 @@
    48.4 +<?xml version="1.0" encoding="UTF-8"?>
    48.5 +<!--
    48.6 +
    48.7 +    Back 2 Browser Bytecode Translator
    48.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    48.9 +
   48.10 +    This program is free software: you can redistribute it and/or modify
   48.11 +    it under the terms of the GNU General Public License as published by
   48.12 +    the Free Software Foundation, version 2 of the License.
   48.13 +
   48.14 +    This program is distributed in the hope that it will be useful,
   48.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   48.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   48.17 +    GNU General Public License for more details.
   48.18 +
   48.19 +    You should have received a copy of the GNU General Public License
   48.20 +    along with this program. Look for COPYING file in the top folder.
   48.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   48.22 +
   48.23 +-->
   48.24 +<project-shared-configuration>
   48.25 +    <!--
   48.26 +This file contains additional configuration written by modules in the NetBeans IDE.
   48.27 +The configuration is intended to be shared among all the users of project and
   48.28 +therefore it is assumed to be part of version control checkout.
   48.29 +Without this configuration present, some functionality in the IDE may be limited or fail altogether.
   48.30 +-->
   48.31 +    <properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
   48.32 +        <!--
   48.33 +Properties that influence various parts of the IDE, especially code formatting and the like. 
   48.34 +You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
   48.35 +That way multiple projects can share the same settings (useful for formatting rules for example).
   48.36 +Any value defined here will override the pom.xml file value but is only applicable to the current project.
   48.37 +-->
   48.38 +        <netbeans.compile.on.save>none</netbeans.compile.on.save>
   48.39 +    </properties>
   48.40 +</project-shared-configuration>
    49.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    49.2 +++ b/javaquery/demo-twitter/nbactions.xml	Mon Oct 07 14:20:58 2013 +0200
    49.3 @@ -0,0 +1,29 @@
    49.4 +<?xml version="1.0" encoding="UTF-8"?>
    49.5 +<!--
    49.6 +
    49.7 +    Back 2 Browser Bytecode Translator
    49.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    49.9 +
   49.10 +    This program is free software: you can redistribute it and/or modify
   49.11 +    it under the terms of the GNU General Public License as published by
   49.12 +    the Free Software Foundation, version 2 of the License.
   49.13 +
   49.14 +    This program is distributed in the hope that it will be useful,
   49.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   49.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   49.17 +    GNU General Public License for more details.
   49.18 +
   49.19 +    You should have received a copy of the GNU General Public License
   49.20 +    along with this program. Look for COPYING file in the top folder.
   49.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   49.22 +
   49.23 +-->
   49.24 +<actions>
   49.25 +    <action>
   49.26 +        <actionName>run</actionName>
   49.27 +        <goals>
   49.28 +            <goal>process-classes</goal>
   49.29 +            <goal>bck2brwsr:brwsr</goal>
   49.30 +        </goals>
   49.31 +    </action>
   49.32 +</actions>
    50.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    50.2 +++ b/javaquery/demo-twitter/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    50.3 @@ -0,0 +1,151 @@
    50.4 +<?xml version="1.0" encoding="UTF-8"?>
    50.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    50.6 +  <modelVersion>4.0.0</modelVersion>
    50.7 +  <parent>
    50.8 +    <artifactId>javaquery</artifactId>
    50.9 +    <groupId>org.apidesign.bck2brwsr</groupId>
   50.10 +    <version>0.9-SNAPSHOT</version>
   50.11 +  </parent>
   50.12 +
   50.13 +  <groupId>org.apidesign.bck2brwsr</groupId>
   50.14 +  <artifactId>demo-twitter</artifactId>
   50.15 +  <version>0.9-SNAPSHOT</version>
   50.16 +  <packaging>jar</packaging>
   50.17 +
   50.18 +  <name>Bck2Brwsr's Twttr</name>
   50.19 +  <description>
   50.20 +      Rewrite of knockoutjs example to use model written in Java and
   50.21 +      execute using Bck2Brwsr virtual machine.
   50.22 +  </description>
   50.23 +
   50.24 +  <repositories>
   50.25 +      <repository>
   50.26 +          <id>java.net</id>
   50.27 +          <name>Java.net</name>
   50.28 +          <url>https://maven.java.net/content/repositories/releases/</url>
   50.29 +          <snapshots>
   50.30 +          </snapshots>
   50.31 +      </repository>
   50.32 +      <repository>
   50.33 +          <id>netbeans</id>
   50.34 +          <name>NetBeans</name>
   50.35 +          <url>http://bits.netbeans.org/maven2/</url>
   50.36 +      </repository>
   50.37 +  </repositories>
   50.38 +  <pluginRepositories>
   50.39 +      <pluginRepository>
   50.40 +          <id>java.net</id>
   50.41 +          <name>Java.net</name>
   50.42 +          <url>https://maven.java.net/content/repositories/releases/</url>
   50.43 +          <snapshots>
   50.44 +          </snapshots>
   50.45 +      </pluginRepository>
   50.46 +  </pluginRepositories>
   50.47 +
   50.48 +  <properties>
   50.49 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   50.50 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
   50.51 +  </properties>
   50.52 +  <build>
   50.53 +      <plugins>
   50.54 +            <plugin>
   50.55 +                <groupId>org.apidesign.bck2brwsr</groupId>
   50.56 +                <artifactId>bck2brwsr-maven-plugin</artifactId>
   50.57 +                <version>${project.version}</version>
   50.58 +                <executions>
   50.59 +                    <execution>
   50.60 +                        <goals>
   50.61 +                            <goal>brwsr</goal>
   50.62 +                            <goal>j2js</goal>
   50.63 +                        </goals>
   50.64 +                    </execution>
   50.65 +                </executions>
   50.66 +                <configuration>
   50.67 +                    <startpage>org/apidesign/bck2brwsr/demo/twitter/index.html</startpage>
   50.68 +                    <javascript>${project.build.directory}/bck2brwsr.js</javascript>
   50.69 +                    <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
   50.70 +                </configuration>
   50.71 +            </plugin>
   50.72 +         <plugin>
   50.73 +            <groupId>org.apache.maven.plugins</groupId>
   50.74 +            <artifactId>maven-compiler-plugin</artifactId>
   50.75 +            <version>2.3.2</version>
   50.76 +            <configuration>
   50.77 +               <source>1.7</source>
   50.78 +               <target>1.7</target>
   50.79 +            </configuration>
   50.80 +         </plugin>
   50.81 +         <plugin>
   50.82 +             <groupId>org.apache.maven.plugins</groupId>
   50.83 +             <artifactId>maven-jar-plugin</artifactId>
   50.84 +             <version>2.4</version>
   50.85 +             <configuration>
   50.86 +                 <archive>
   50.87 +                     <manifest>
   50.88 +                         <addClasspath>true</addClasspath>
   50.89 +                         <classpathPrefix>lib/</classpathPrefix>
   50.90 +                     </manifest>
   50.91 +                 </archive>
   50.92 +             </configuration>
   50.93 +         </plugin>
   50.94 +         <plugin>
   50.95 +           <groupId>org.apache.maven.plugins</groupId>
   50.96 +           <artifactId>maven-deploy-plugin</artifactId>
   50.97 +           <version>2.7</version>
   50.98 +           <configuration>
   50.99 +             <skip>true</skip>
  50.100 +           </configuration>
  50.101 +         </plugin>      
  50.102 +         <plugin>
  50.103 +             <artifactId>maven-assembly-plugin</artifactId>
  50.104 +             <version>2.4</version>
  50.105 +             <executions>
  50.106 +                 <execution>
  50.107 +                     <id>distro-assembly</id>
  50.108 +                     <phase>package</phase>
  50.109 +                     <goals>
  50.110 +                         <goal>single</goal>
  50.111 +                     </goals>
  50.112 +                     <configuration>
  50.113 +                         <descriptors>
  50.114 +                             <descriptor>bck2brwsr-assembly.xml</descriptor>
  50.115 +                         </descriptors>
  50.116 +                     </configuration>
  50.117 +                 </execution>
  50.118 +             </executions>                
  50.119 +         </plugin>      
  50.120 +      </plugins>
  50.121 +  </build>
  50.122 +
  50.123 +  <dependencies>
  50.124 +    <dependency>
  50.125 +      <groupId>org.apidesign.bck2brwsr</groupId>
  50.126 +      <artifactId>emul</artifactId>
  50.127 +      <version>${project.version}</version>
  50.128 +      <classifier>rt</classifier>
  50.129 +    </dependency>
  50.130 +    <dependency>
  50.131 +      <groupId>org.apidesign.bck2brwsr</groupId>
  50.132 +      <artifactId>javaquery.api</artifactId>
  50.133 +      <version>${project.version}</version>
  50.134 +    </dependency>
  50.135 +    <dependency>
  50.136 +      <groupId>org.testng</groupId>
  50.137 +      <artifactId>testng</artifactId>
  50.138 +      <version>6.5.2</version>
  50.139 +      <scope>test</scope>
  50.140 +    </dependency>
  50.141 +    <dependency>
  50.142 +      <groupId>org.apidesign.bck2brwsr</groupId>
  50.143 +      <artifactId>vmtest</artifactId>
  50.144 +      <version>${project.version}</version>
  50.145 +      <scope>test</scope>
  50.146 +    </dependency>
  50.147 +    <dependency>
  50.148 +      <groupId>org.apidesign.bck2brwsr</groupId>
  50.149 +      <artifactId>launcher.http</artifactId>
  50.150 +      <version>${project.version}</version>
  50.151 +      <scope>runtime</scope>
  50.152 +    </dependency>
  50.153 +  </dependencies>
  50.154 +</project>
    51.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    51.2 +++ b/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java	Mon Oct 07 14:20:58 2013 +0200
    51.3 @@ -0,0 +1,194 @@
    51.4 +/**
    51.5 + * Back 2 Browser Bytecode Translator
    51.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    51.7 + *
    51.8 + * This program is free software: you can redistribute it and/or modify
    51.9 + * it under the terms of the GNU General Public License as published by
   51.10 + * the Free Software Foundation, version 2 of the License.
   51.11 + *
   51.12 + * This program is distributed in the hope that it will be useful,
   51.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   51.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   51.15 + * GNU General Public License for more details.
   51.16 + *
   51.17 + * You should have received a copy of the GNU General Public License
   51.18 + * along with this program. Look for COPYING file in the top folder.
   51.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   51.20 + */
   51.21 +package org.apidesign.bck2brwsr.demo.twitter;
   51.22 +
   51.23 +import java.util.Arrays;
   51.24 +import java.util.List;
   51.25 +import org.apidesign.bck2brwsr.htmlpage.api.*;
   51.26 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
   51.27 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
   51.28 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
   51.29 +
   51.30 +/** Controller class for access to Twitter.
   51.31 + * 
   51.32 + * @author Jaroslav Tulach
   51.33 + */
   51.34 +@Page(xhtml="index.html", className="TwitterModel", properties={
   51.35 +    @Property(name="savedLists", type=Tweeters.class, array = true),
   51.36 +    @Property(name="activeTweetersName", type=String.class),
   51.37 +    @Property(name="activeTweeters", type=String.class, array = true),
   51.38 +    @Property(name="userNameToAdd", type=String.class),
   51.39 +    @Property(name="currentTweets", type=Tweet.class, array = true)
   51.40 +})
   51.41 +public class TwitterClient {
   51.42 +    @Model(className = "Tweeters", properties = {
   51.43 +        @Property(name="name", type = String.class),
   51.44 +        @Property(name="userNames", type = String.class, array = true)
   51.45 +    })
   51.46 +    static class Twttrs {
   51.47 +    }
   51.48 +    @Model(className = "Tweet", properties = {
   51.49 +        @Property(name = "from_user", type = String.class),
   51.50 +        @Property(name = "from_user_id", type = int.class),
   51.51 +        @Property(name = "profile_image_url", type = String.class),
   51.52 +        @Property(name = "text", type = String.class),
   51.53 +        @Property(name = "created_at", type = String.class),
   51.54 +    })
   51.55 +    static final class Twt {
   51.56 +        @ComputedProperty static String html(String text) {
   51.57 +            StringBuilder sb = new StringBuilder(320);
   51.58 +            for (int pos = 0;;) {
   51.59 +                int http = text.indexOf("http", pos);
   51.60 +                if (http == -1) {
   51.61 +                    sb.append(text.substring(pos));
   51.62 +                    return sb.toString();
   51.63 +                }
   51.64 +                int spc = text.indexOf(' ', http);
   51.65 +                if (spc == -1) {
   51.66 +                    spc = text.length();
   51.67 +                }
   51.68 +                sb.append(text.substring(pos, http));
   51.69 +                String url = text.substring(http, spc);
   51.70 +                sb.append("<a href='").append(url).append("'>").append(url).append("</a>");
   51.71 +                pos = spc;
   51.72 +            }
   51.73 +        }
   51.74 +        
   51.75 +        @ComputedProperty static String userUrl(String from_user) {
   51.76 +            return "http://twitter.com/" + from_user;
   51.77 +        }
   51.78 +    }
   51.79 +    @Model(className = "TwitterQuery", properties = {
   51.80 +        @Property(array = true, name = "results", type = Twt.class)
   51.81 +    })
   51.82 +    public static final class TwttrQr {
   51.83 +    }
   51.84 +    
   51.85 +    @OnReceive(url="{root}/search.json?{query}&callback={me}", jsonp="me")
   51.86 +    static void queryTweets(TwitterModel page, TwitterQuery q) {
   51.87 +        page.getCurrentTweets().clear();
   51.88 +        page.getCurrentTweets().addAll(q.getResults());
   51.89 +    }
   51.90 +    
   51.91 +    @OnPropertyChange("activeTweetersName")
   51.92 +    static void changeTweetersList(TwitterModel model) {
   51.93 +        Tweeters people = findByName(model.getSavedLists(), model.getActiveTweetersName());        
   51.94 +        model.getActiveTweeters().clear();
   51.95 +        model.getActiveTweeters().addAll(people.getUserNames());
   51.96 +    }
   51.97 +    
   51.98 +    @OnPropertyChange({ "activeTweeters", "activeTweetersCount" })
   51.99 +    static void refreshTweets(TwitterModel model) {
  51.100 +        StringBuilder sb = new StringBuilder();
  51.101 +        sb.append("rpp=25&q=");
  51.102 +        String sep = "";
  51.103 +        for (String p : model.getActiveTweeters()) {
  51.104 +            sb.append(sep);
  51.105 +            sb.append("from:");
  51.106 +            sb.append(p);
  51.107 +            sep = " OR ";
  51.108 +        }
  51.109 +        model.queryTweets("http://search.twitter.com", sb.toString());
  51.110 +    }
  51.111 +    
  51.112 +    static {
  51.113 +        final TwitterModel model = new TwitterModel();
  51.114 +        final List<Tweeters> svdLst = model.getSavedLists();
  51.115 +        svdLst.add(newTweeters("API Design", "JaroslavTulach"));
  51.116 +        svdLst.add(newTweeters("Celebrities", "JohnCleese", "MCHammer", "StephenFry", "algore", "StevenSanderson"));
  51.117 +        svdLst.add(newTweeters("Microsoft people", "BillGates", "shanselman", "ScottGu"));
  51.118 +        svdLst.add(newTweeters("NetBeans", "GeertjanW","monacotoni", "NetBeans", "petrjiricka"));
  51.119 +        svdLst.add(newTweeters("Tech pundits", "Scobleizer", "LeoLaporte", "techcrunch", "BoingBoing", "timoreilly", "codinghorror"));
  51.120 +
  51.121 +        model.setActiveTweetersName("NetBeans");
  51.122 +
  51.123 +        model.applyBindings();
  51.124 +    }
  51.125 +    
  51.126 +    @ComputedProperty
  51.127 +    static boolean hasUnsavedChanges(List<String> activeTweeters, List<Tweeters> savedLists, String activeTweetersName) {
  51.128 +        Tweeters tw = findByName(savedLists, activeTweetersName);
  51.129 +        if (activeTweeters == null) {
  51.130 +            return false;
  51.131 +        }
  51.132 +        return !tw.getUserNames().equals(activeTweeters);
  51.133 +    }
  51.134 +    
  51.135 +    @ComputedProperty
  51.136 +    static int activeTweetersCount(List<String> activeTweeters) {
  51.137 +        return activeTweeters.size();
  51.138 +    }
  51.139 +    
  51.140 +    @ComputedProperty
  51.141 +    static boolean userNameToAddIsValid(
  51.142 +        String userNameToAdd, String activeTweetersName, List<Tweeters> savedLists, List<String> activeTweeters
  51.143 +    ) {
  51.144 +        return userNameToAdd != null && 
  51.145 +            userNameToAdd.matches("[a-zA-Z0-9_]{1,15}") &&
  51.146 +            !activeTweeters.contains(userNameToAdd);
  51.147 +    }
  51.148 +    
  51.149 +    @OnFunction
  51.150 +    static void deleteList(TwitterModel model) {
  51.151 +        final List<Tweeters> sl = model.getSavedLists();
  51.152 +        sl.remove(findByName(sl, model.getActiveTweetersName()));
  51.153 +        if (sl.isEmpty()) {
  51.154 +            final Tweeters t = new Tweeters();
  51.155 +            t.setName("New");
  51.156 +            sl.add(t);
  51.157 +        }
  51.158 +        model.setActiveTweetersName(sl.get(0).getName());
  51.159 +    }
  51.160 +    
  51.161 +    @OnFunction
  51.162 +    static void saveChanges(TwitterModel model) {
  51.163 +        Tweeters t = findByName(model.getSavedLists(), model.getActiveTweetersName());
  51.164 +        int indx = model.getSavedLists().indexOf(t);
  51.165 +        if (indx != -1) {
  51.166 +            t.setName(model.getActiveTweetersName());
  51.167 +            t.getUserNames().clear();
  51.168 +            t.getUserNames().addAll(model.getActiveTweeters());
  51.169 +        }
  51.170 +    }
  51.171 +    
  51.172 +    @OnFunction
  51.173 +    static void addUser(TwitterModel model) {
  51.174 +        String n = model.getUserNameToAdd();
  51.175 +        model.getActiveTweeters().add(n);
  51.176 +    }
  51.177 +    @OnFunction
  51.178 +    static void removeUser(String data, TwitterModel model) {
  51.179 +        model.getActiveTweeters().remove(data);
  51.180 +    }
  51.181 +    
  51.182 +    private static Tweeters findByName(List<Tweeters> list, String name) {
  51.183 +        for (Tweeters l : list) {
  51.184 +            if (l.getName() != null && l.getName().equals(name)) {
  51.185 +                return l;
  51.186 +            }
  51.187 +        }
  51.188 +        return list.isEmpty() ? new Tweeters() : list.get(0);
  51.189 +    }
  51.190 +    
  51.191 +    private static Tweeters newTweeters(String listName, String... userNames) {
  51.192 +        Tweeters t = new Tweeters();
  51.193 +        t.setName(listName);
  51.194 +        t.getUserNames().addAll(Arrays.asList(userNames));
  51.195 +        return t;
  51.196 +    }
  51.197 +}
    52.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    52.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/index.html	Mon Oct 07 14:20:58 2013 +0200
    52.3 @@ -0,0 +1,99 @@
    52.4 +<?xml version="1.0" encoding="UTF-8"?>
    52.5 +<!--
    52.6 +
    52.7 +    Back 2 Browser Bytecode Translator
    52.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    52.9 +
   52.10 +    This program is free software: you can redistribute it and/or modify
   52.11 +    it under the terms of the GNU General Public License as published by
   52.12 +    the Free Software Foundation, version 2 of the License.
   52.13 +
   52.14 +    This program is distributed in the hope that it will be useful,
   52.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   52.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   52.17 +    GNU General Public License for more details.
   52.18 +
   52.19 +    You should have received a copy of the GNU General Public License
   52.20 +    along with this program. Look for COPYING file in the top folder.
   52.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   52.22 +
   52.23 +-->
   52.24 +
   52.25 +<!--
   52.26 +    Copied from knockout.js Twitter example:
   52.27 +    http://knockoutjs.com/examples/twitter.html
   52.28 +-->
   52.29 +
   52.30 +<!DOCTYPE html>
   52.31 +<html xmlns="http://www.w3.org/1999/xhtml">
   52.32 +    <head>
   52.33 +        <title>Bck2Brwsr's Twitter</title>
   52.34 +    </head>
   52.35 +    <body>
   52.36 +        <link href='twitterExample.css' rel='Stylesheet' ></link>
   52.37 +        
   52.38 +        <style type='text/css'>
   52.39 +           .liveExample select { height: 1.7em; }
   52.40 +           .liveExample button { height: 2em; }
   52.41 +        </style>
   52.42 +        
   52.43 +        
   52.44 +        <h2>Bck2Brwsr's Twitter</h2>
   52.45 +        
   52.46 +        <p>
   52.47 +        This code based on original <a href="http://knockoutjs.com/examples/twitter.html">knockout.js Twitter example</a> and
   52.48 +        uses almost unmodified HTML code. It just changes the model. It 
   52.49 +        is written in Java language and it is executed using <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
   52.50 +        virtual machine. The Java source code has about 190 lines and is available 
   52.51 +        <a href="http://source.apidesign.org/hg/bck2brwsr/file/7fc6b7e9c982/javaquery/demo-twitter/src/main/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClient.java">here</a>
   52.52 +        - in fact it may even be more dense than the original JavaScript model.
   52.53 +        </p>
   52.54 +        
   52.55 +        <div class='liveExample'>
   52.56 +            <div class='configuration'>
   52.57 +                <div class='listChooser'>
   52.58 +                    <button data-bind='click: deleteList, enable: activeTweetersName'>Delete</button>
   52.59 +                    <button data-bind='click: saveChanges, enable: hasUnsavedChanges'>Save</button> 
   52.60 +                    <select data-bind='options: savedLists, optionsValue: "name", value: activeTweetersName'> </select>
   52.61 +                </div>
   52.62 +
   52.63 +                <p>Currently viewing <span data-bind='text: activeTweetersCount'> </span> user(s):</p>
   52.64 +                <div class='currentUsers' >
   52.65 +                    <ul data-bind='foreach: activeTweeters'>
   52.66 +                        <li>
   52.67 +                            <button data-bind='click: $root.removeUser'>Remove</button>
   52.68 +                            <div data-bind='text: $data'> </div>
   52.69 +                        </li>
   52.70 +                    </ul>
   52.71 +                </div>
   52.72 +
   52.73 +                <form data-bind='submit: addUser'>
   52.74 +                    <label>Add user:</label>
   52.75 +                    <input data-bind='value: userNameToAdd, valueUpdate: "keyup", css: { invalid: !userNameToAddIsValid() }' />
   52.76 +                    <button data-bind='enable: userNameToAddIsValid' type='submit'>Add</button>
   52.77 +                </form>
   52.78 +            </div>
   52.79 +            <div class='tweets'>
   52.80 +                <div class='loadingIndicator'>Loading...</div>
   52.81 +                <table data-bind='foreach: currentTweets' width='100%'>
   52.82 +                    <tr>
   52.83 +                        <td><img data-bind='attr: { src: profile_image_url }' /></td>
   52.84 +                        <td>
   52.85 +                            <a class='twitterUser' data-bind='attr: { href: userUrl }, text: from_user'> </a>
   52.86 +                            <span data-bind='html: html'> </span>
   52.87 +                            <div class='tweetInfo' data-bind='text: created_at'> </div>
   52.88 +                        </td>
   52.89 +                    </tr>
   52.90 +                </table>
   52.91 +            </div>
   52.92 +        </div>
   52.93 +        
   52.94 +        <script src="bck2brwsr.js"></script>
   52.95 +        <script type="text/javascript">
   52.96 +            var vm = bck2brwsr('demo-twitter-0.8-SNAPSHOT.jar');
   52.97 +            vm.loadClass('org.apidesign.bck2brwsr.demo.twitter.TwitterClient');
   52.98 +        </script>
   52.99 +
  52.100 +
  52.101 +    </body>
  52.102 +</html>
    53.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    53.2 +++ b/javaquery/demo-twitter/src/main/resources/org/apidesign/bck2brwsr/demo/twitter/twitterExample.css	Mon Oct 07 14:20:58 2013 +0200
    53.3 @@ -0,0 +1,50 @@
    53.4 +/**
    53.5 + * Back 2 Browser Bytecode Translator
    53.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    53.7 + *
    53.8 + * This program is free software: you can redistribute it and/or modify
    53.9 + * it under the terms of the GNU General Public License as published by
   53.10 + * the Free Software Foundation, version 2 of the License.
   53.11 + *
   53.12 + * This program is distributed in the hope that it will be useful,
   53.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   53.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   53.15 + * GNU General Public License for more details.
   53.16 + *
   53.17 + * You should have received a copy of the GNU General Public License
   53.18 + * along with this program. Look for COPYING file in the top folder.
   53.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   53.20 + */
   53.21 +
   53.22 +/*
   53.23 +    Copied from knockout.js Twitter example:
   53.24 +    http://knockoutjs.com/examples/twitter.html
   53.25 +*/
   53.26 +
   53.27 +.configuration, .tweets, .tweets td { font-family: Verdana; font-size: 13px; }
   53.28 +.configuration { background-color: #DEDEDE; border: 2px solid gray; float:left; height: 40em; width: 40%; padding: 0.5em; border-right-width:0; }
   53.29 +.tweets { width: 55%; border: 2px solid gray; height: 40em; overflow: scroll; overflow-x: hidden; background-color: Black; color: White; padding: 0.5em; position: relative; }
   53.30 +.tweets table { border-width: 0;}
   53.31 +.tweets tr { vertical-align: top; }
   53.32 +.tweets td { padding: 0.4em 0.3em 1em 0.4em; border-width: 0; }
   53.33 +.tweets img { width: 4em; }
   53.34 +.tweetInfo { color: Gray; font-size: 0.9em; }
   53.35 +.twitterUser { color: #77AAFF; text-decoration: none; font-size: 1.1em; font-weight: bold; }
   53.36 +input.invalid { border: 1px solid red !important; background-color: #FFAAAA !important; }
   53.37 +
   53.38 +.listChooser select, .listChooser button { vertical-align:top; }
   53.39 +.listChooser select { width: 60%; font-size:1.2em; height:1.4em; }
   53.40 +.listChooser button { width: 19%; height:1.68em; float:right; }
   53.41 +
   53.42 +.currentUsers { height: 28em; overflow-y: auto; overflow-x: hidden; }
   53.43 +.currentUsers button { float: right; height: 2.5em; margin: 0.1em; padding-left: 1em; padding-right: 1em; }
   53.44 +.currentUsers ul, .configuration li { list-style: none; margin: 0; padding: 0 }
   53.45 +.currentUsers li { height: 2.4em; font-size: 1.2em; background-color: #A7D0E3; border: 1px solid gray; margin-bottom: 0.3em; -webkit-border-radius: 5px; -moz-border-radius: 5px; -webkit-box-shadow: 0 0.2em 0.5em gray; -moz-box-shadow: 0 0.2em 0.5em gray; }
   53.46 +.currentUsers li div { padding: 0.6em; }
   53.47 +.currentUsers li:hover { background-color: #EEC; }
   53.48 +
   53.49 +.configuration form label { width: 25%; display: inline-block; text-align:right; overflow: hidden; }
   53.50 +.configuration form input { width:40%; font-size: 1.3em; border:1px solid silver; background-color: White; padding: 0.1em; }
   53.51 +.configuration form button { width: 20%; margin-left: 0.3em; height: 2em; }
   53.52 +
   53.53 +.loadingIndicator { position: absolute; top: 0.1em; left: 0.1em; font: 0.8em Arial; background-color: #229; color: White; padding: 0.2em 0.5em 0.2em 0.5em; display: none; }
    54.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    54.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterClientTest.java	Mon Oct 07 14:20:58 2013 +0200
    54.3 @@ -0,0 +1,67 @@
    54.4 +/**
    54.5 + * Back 2 Browser Bytecode Translator
    54.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    54.7 + *
    54.8 + * This program is free software: you can redistribute it and/or modify
    54.9 + * it under the terms of the GNU General Public License as published by
   54.10 + * the Free Software Foundation, version 2 of the License.
   54.11 + *
   54.12 + * This program is distributed in the hope that it will be useful,
   54.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   54.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   54.15 + * GNU General Public License for more details.
   54.16 + *
   54.17 + * You should have received a copy of the GNU General Public License
   54.18 + * along with this program. Look for COPYING file in the top folder.
   54.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   54.20 + */
   54.21 +package org.apidesign.bck2brwsr.demo.twitter;
   54.22 +
   54.23 +import java.util.List;
   54.24 +import static org.testng.Assert.*;
   54.25 +import org.testng.annotations.BeforeMethod;
   54.26 +import org.testng.annotations.Test;
   54.27 +
   54.28 +/** We can unit test the TwitterModel smoothly.
   54.29 + *
   54.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   54.31 + */
   54.32 +public class TwitterClientTest {
   54.33 +    private TwitterModel model;
   54.34 +    
   54.35 +
   54.36 +    @BeforeMethod
   54.37 +    public void initModel() {
   54.38 +        model = new TwitterModel().applyBindings();
   54.39 +    }
   54.40 +
   54.41 +    @Test public void testIsValidToAdd() {
   54.42 +        model.setUserNameToAdd("Joe");
   54.43 +        Tweeters t = new Tweeters();
   54.44 +        t.setName("test");
   54.45 +        model.getSavedLists().add(t);
   54.46 +        model.setActiveTweetersName("test");
   54.47 +        
   54.48 +        assertTrue(model.isUserNameToAddIsValid(), "Joe is OK");
   54.49 +        TwitterClient.addUser(model);
   54.50 +        assertFalse(model.isUserNameToAddIsValid(), "Can't add Joe for the 2nd time");
   54.51 +        assertEquals(t.getUserNames().size(), 0, "Original tweeters list remains empty");
   54.52 +        
   54.53 +        List<String> mod = model.getActiveTweeters();
   54.54 +        assertTrue(model.isHasUnsavedChanges(), "We have modifications");
   54.55 +        assertEquals(mod.size(), 1, "One element in the list");
   54.56 +        assertEquals(mod.get(0), "Joe", "Its name is Joe");
   54.57 +        
   54.58 +        assertSame(model.getActiveTweeters(), mod, "Editing list is the modified one");
   54.59 +        
   54.60 +        TwitterClient.saveChanges(model);
   54.61 +        assertFalse(model.isHasUnsavedChanges(), "Does not have anything to save");
   54.62 +        
   54.63 +        assertSame(model.getActiveTweeters(), mod, "Still editing the old modified one");
   54.64 +    }
   54.65 +    
   54.66 +    @Test public void httpAtTheEnd() {
   54.67 +        String res = TwitterClient.Twt.html("Ahoj http://kuk");
   54.68 +        assertEquals(res, "Ahoj <a href='http://kuk'>http://kuk</a>");
   54.69 +    }
   54.70 +}
    55.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    55.2 +++ b/javaquery/demo-twitter/src/test/java/org/apidesign/bck2brwsr/demo/twitter/TwitterProtocolTest.java	Mon Oct 07 14:20:58 2013 +0200
    55.3 @@ -0,0 +1,94 @@
    55.4 +/**
    55.5 + * Back 2 Browser Bytecode Translator
    55.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    55.7 + *
    55.8 + * This program is free software: you can redistribute it and/or modify
    55.9 + * it under the terms of the GNU General Public License as published by
   55.10 + * the Free Software Foundation, version 2 of the License.
   55.11 + *
   55.12 + * This program is distributed in the hope that it will be useful,
   55.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   55.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   55.15 + * GNU General Public License for more details.
   55.16 + *
   55.17 + * You should have received a copy of the GNU General Public License
   55.18 + * along with this program. Look for COPYING file in the top folder.
   55.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   55.20 + */
   55.21 +package org.apidesign.bck2brwsr.demo.twitter;
   55.22 +
   55.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   55.24 +import org.apidesign.bck2brwsr.vmtest.Http;
   55.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   55.26 +import org.testng.annotations.Factory;
   55.27 +
   55.28 +/**
   55.29 + *
   55.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   55.31 + */
   55.32 +public class TwitterProtocolTest {
   55.33 +    private TwitterModel page;
   55.34 +    @Http(@Http.Resource(
   55.35 +        path = "/search.json",
   55.36 +        mimeType = "application/json",
   55.37 +        parameters = {"callback"},
   55.38 +        content = "$0({\"completed_in\":0.04,\"max_id\":320055706885689344,\"max_id_str\""
   55.39 +        + ":\"320055706885689344\",\"page\":1,\"query\":\"from%3AJaroslavTulach\",\"refresh_url\":"
   55.40 +        + "\"?since_id=320055706885689344&q=from%3AJaroslavTulach\","
   55.41 +        + "\"results\":[{\"created_at\":\"Fri, 05 Apr 2013 06:10:01 +0000\","
   55.42 +        + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
   55.43 +        + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":320055706885689344,"
   55.44 +        + "\"id_str\":\"320055706885689344\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
   55.45 +        + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.46 +        + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.47 +        + "\"source\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"text\":"
   55.48 +        + "\"@tom_enebo Amzng! Not that I would like #ruby, but I am really glad you guys stabilized the plugin + "
   55.49 +        + "made it work in #netbeans 7.3! Gd wrk.\",\"to_user\":\"tom_enebo\",\"to_user_id\":14498747,"
   55.50 +        + "\"to_user_id_str\":\"14498747\",\"to_user_name\":\"tom_enebo\",\"in_reply_to_status_id\":319832359509839872,"
   55.51 +        + "\"in_reply_to_status_id_str\":\"319832359509839872\"},{\"created_at\":\"Thu, 04 Apr 2013 07:33:06 +0000\","
   55.52 +        + "\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,\"from_user_id_str\":"
   55.53 +        + "\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,\"id\":319714227088678913,"
   55.54 +        + "\"id_str\":\"319714227088678913\",\"iso_language_code\":\"en\",\"metadata\":{\"result_type\":"
   55.55 +        + "\"recent\"},\"profile_image_url\":\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.56 +        + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.57 +        + "\"source\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"text\":"
   55.58 +        + "\"RT @drkrab: At #erlangfactory @joerl: Frameworks grow in complexity until nobody can use them.\"},"
   55.59 +        + "{\"created_at\":\"Tue, 02 Apr 2013 07:44:34 +0000\",\"from_user\":\"JaroslavTulach\","
   55.60 +        + "\"from_user_id\":420944648,\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\","
   55.61 +        + "\"geo\":null,\"id\":318992336145248256,\"id_str\":\"318992336145248256\",\"iso_language_code\":\"en\","
   55.62 +        + "\"metadata\":{\"result_type\":\"recent\"},\"profile_image_url\":"
   55.63 +        + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.64 +        + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.65 +        + "\"source\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"text\":"
   55.66 +        + "\"Twitter renamed to twttr http:\\/\\/t.co\\/tqaN4T1xlZ - good, I don't have to rename #bck2brwsr!\"},"
   55.67 +        + "{\"created_at\":\"Sun, 31 Mar 2013 03:52:04 +0000\",\"from_user\":\"JaroslavTulach\",\"from_user_id\":420944648,"
   55.68 +        + "\"from_user_id_str\":\"420944648\",\"from_user_name\":\"Jaroslav Tulach\",\"geo\":null,"
   55.69 +        + "\"id\":318209051223789568,\"id_str\":\"318209051223789568\",\"iso_language_code\":\"en\",\"metadata\":"
   55.70 +        + "{\"result_type\":\"recent\"},\"profile_image_url\":"
   55.71 +        + "\"http:\\/\\/a0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.72 +        + "\"profile_image_url_https\":\"https:\\/\\/si0.twimg.com\\/profile_images\\/1656828312\\/jst_normal.gif\","
   55.73 +        + "\"source\":\"&lt;a href=&quot;http:\\/\\/twitter.com\\/&quot;&gt;web&lt;\\/a&gt;\",\"text\":"
   55.74 +        + "\"Math proofs without words. Ingenious: http:\\/\\/t.co\\/sz7yVbfpGw\"}],\"results_per_page\":100,"
   55.75 +        + "\"since_id\":0,\"since_id_str\":\"0\"})"
   55.76 +    ))
   55.77 +    @BrwsrTest public void readFromTwttr() throws InterruptedException {
   55.78 +        if (page == null) {
   55.79 +            page = new TwitterModel();
   55.80 +            page.applyBindings();
   55.81 +            page.queryTweets("", "q=xyz");
   55.82 +        }
   55.83 +
   55.84 +        if (page.getCurrentTweets().isEmpty()) {
   55.85 +            throw new InterruptedException();
   55.86 +        }
   55.87 +
   55.88 +        assert 4 == page.getCurrentTweets().size() : "Four tweets: " + page.getCurrentTweets();
   55.89 +        
   55.90 +        String firstDate = page.getCurrentTweets().get(0).getCreated_at();
   55.91 +        assert "Fri, 05 Apr 2013 06:10:01 +0000".equals(firstDate) : "Date is OK: " + firstDate;
   55.92 +    }
   55.93 +    
   55.94 +    @Factory public static Object[] create() {
   55.95 +        return VMTest.create(TwitterProtocolTest.class);
   55.96 +    }
   55.97 +}
    56.1 --- a/javaquery/pom.xml	Wed Feb 27 17:50:47 2013 +0100
    56.2 +++ b/javaquery/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    56.3 @@ -4,16 +4,17 @@
    56.4    <parent>
    56.5      <artifactId>bck2brwsr</artifactId>
    56.6      <groupId>org.apidesign</groupId>
    56.7 -    <version>0.3-SNAPSHOT</version>
    56.8 +    <version>0.9-SNAPSHOT</version>
    56.9    </parent>
   56.10    <groupId>org.apidesign.bck2brwsr</groupId>
   56.11    <artifactId>javaquery</artifactId>
   56.12 -  <version>0.3-SNAPSHOT</version>
   56.13 +  <version>0.9-SNAPSHOT</version>
   56.14    <packaging>pom</packaging>
   56.15    <name>JavaQuery API and Demo</name>
   56.16      <modules>
   56.17          <module>api</module>
   56.18          <module>demo-calculator</module>
   56.19          <module>demo-calculator-dynamic</module>
   56.20 -    </modules>
   56.21 -</project>
   56.22 +    <module>demo-twitter</module>
   56.23 +  </modules>
   56.24 +</project>
   56.25 \ No newline at end of file
    57.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    57.2 +++ b/ko/archetype-test/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    57.3 @@ -0,0 +1,48 @@
    57.4 +<?xml version="1.0"?>
    57.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    57.6 +    <modelVersion>4.0.0</modelVersion>
    57.7 +    <parent>
    57.8 +        <groupId>org.apidesign.bck2brwsr</groupId>
    57.9 +        <artifactId>ko</artifactId>
   57.10 +        <version>0.9-SNAPSHOT</version>
   57.11 +    </parent>
   57.12 +    <groupId>org.apidesign.bck2brwsr</groupId>
   57.13 +    <artifactId>ko-archetype-test</artifactId>
   57.14 +    <version>0.9-SNAPSHOT</version>
   57.15 +    <name>Knockout Bck2Brwsr Archetype Test</name>
   57.16 +    <url>http://maven.apache.org</url>
   57.17 +    <description>Verifies the Knockout &amp; net.java.html.json archetype behaves properly.</description>
   57.18 +    <properties>
   57.19 +        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   57.20 +    </properties>
   57.21 +    <dependencies>
   57.22 +        <dependency>
   57.23 +            <groupId>${project.groupId}</groupId>
   57.24 +            <artifactId>knockout4j-archetype</artifactId>
   57.25 +            <version>${project.version}</version>
   57.26 +        </dependency>
   57.27 +        <dependency>
   57.28 +            <groupId>org.testng</groupId>
   57.29 +            <artifactId>testng</artifactId>
   57.30 +            <scope>test</scope>
   57.31 +        </dependency>
   57.32 +        <dependency>                                
   57.33 +            <groupId>org.apache.maven.shared</groupId>
   57.34 +            <artifactId>maven-verifier</artifactId>
   57.35 +            <version>1.4</version>
   57.36 +            <scope>test</scope>
   57.37 +        </dependency>
   57.38 +        <dependency>
   57.39 +            <groupId>${project.groupId}</groupId>
   57.40 +            <artifactId>ko-fx</artifactId>
   57.41 +            <version>${project.version}</version>
   57.42 +            <scope>provided</scope>
   57.43 +        </dependency>
   57.44 +        <dependency>
   57.45 +            <groupId>${project.groupId}</groupId>
   57.46 +            <artifactId>ko-bck2brwsr</artifactId>
   57.47 +            <version>${project.version}</version>
   57.48 +            <scope>provided</scope>
   57.49 +        </dependency>
   57.50 +    </dependencies>
   57.51 +</project>
    58.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    58.2 +++ b/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/ArchetypeVersionTest.java	Mon Oct 07 14:20:58 2013 +0200
    58.3 @@ -0,0 +1,140 @@
    58.4 +/**
    58.5 + * Back 2 Browser Bytecode Translator
    58.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    58.7 + *
    58.8 + * This program is free software: you can redistribute it and/or modify
    58.9 + * it under the terms of the GNU General Public License as published by
   58.10 + * the Free Software Foundation, version 2 of the License.
   58.11 + *
   58.12 + * This program is distributed in the hope that it will be useful,
   58.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   58.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   58.15 + * GNU General Public License for more details.
   58.16 + *
   58.17 + * You should have received a copy of the GNU General Public License
   58.18 + * along with this program. Look for COPYING file in the top folder.
   58.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   58.20 + */
   58.21 +package org.apidesign.bck2brwsr.ko.archetype.test;
   58.22 +
   58.23 +import java.io.IOException;
   58.24 +import java.net.URL;
   58.25 +import javax.xml.XMLConstants;
   58.26 +import javax.xml.parsers.DocumentBuilderFactory;
   58.27 +import javax.xml.parsers.ParserConfigurationException;
   58.28 +import javax.xml.xpath.XPathConstants;
   58.29 +import javax.xml.xpath.XPathExpression;
   58.30 +import javax.xml.xpath.XPathExpressionException;
   58.31 +import javax.xml.xpath.XPathFactory;
   58.32 +import javax.xml.xpath.XPathFactoryConfigurationException;
   58.33 +import org.testng.annotations.Test;
   58.34 +import static org.testng.Assert.*;
   58.35 +import org.testng.annotations.BeforeClass;
   58.36 +import org.w3c.dom.Document;
   58.37 +import org.w3c.dom.NodeList;
   58.38 +import org.xml.sax.SAXException;
   58.39 +
   58.40 +/**
   58.41 + *
   58.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   58.43 + */
   58.44 +public class ArchetypeVersionTest {
   58.45 +    private String version;
   58.46 +    
   58.47 +    public ArchetypeVersionTest() {
   58.48 +    }
   58.49 +    
   58.50 +    @BeforeClass public void readCurrentVersion() throws Exception {
   58.51 +        version = findCurrentVersion();
   58.52 +        assertFalse(version.isEmpty(), "There should be some version string");
   58.53 +    }
   58.54 +    
   58.55 +
   58.56 +    @Test public void testComparePomDepsVersions() throws Exception {
   58.57 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   58.58 +        URL r = l.getResource("archetype-resources/pom.xml");
   58.59 +        assertNotNull(r, "Archetype pom found");
   58.60 +        
   58.61 +        final XPathFactory fact = XPathFactory.newInstance();
   58.62 +        XPathExpression xp2 = fact.newXPath().compile(
   58.63 +            "//properties/net.java.html.version/text()"
   58.64 +        );
   58.65 +        
   58.66 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
   58.67 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
   58.68 +        
   58.69 +        int snapshot = arch.indexOf("-SNAPSHOT");
   58.70 +        if (snapshot >= 0) {
   58.71 +            arch = arch.substring(0, snapshot);
   58.72 +        }
   58.73 +
   58.74 +        assertTrue(arch.matches("[0-9\\.]+"), "net.java.html.json version seems valid: " + arch);
   58.75 +    }
   58.76 +    
   58.77 +    @Test public void testCheckLauncher() throws Exception {
   58.78 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   58.79 +        URL r = l.getResource("archetype-resources/pom.xml");
   58.80 +        assertNotNull(r, "Archetype pom found");
   58.81 +        
   58.82 +        final XPathFactory fact = XPathFactory.newInstance();
   58.83 +        XPathExpression xp2 = fact.newXPath().compile(
   58.84 +            "//properties/bck2brwsr.launcher.version/text()"
   58.85 +        );
   58.86 +        
   58.87 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
   58.88 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
   58.89 +
   58.90 +        assertEquals(arch, version, "launcher dependency is on more recent version");
   58.91 +    }
   58.92 +    
   58.93 +    @Test public void testCheckBck2Brwsr() throws Exception {
   58.94 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
   58.95 +        URL r = l.getResource("archetype-resources/pom.xml");
   58.96 +        assertNotNull(r, "Archetype pom found");
   58.97 +        
   58.98 +        final XPathFactory fact = XPathFactory.newInstance();
   58.99 +        XPathExpression xp2 = fact.newXPath().compile(
  58.100 +            "//properties/bck2brwsr.version/text()"
  58.101 +        );
  58.102 +        
  58.103 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  58.104 +        String arch = (String) xp2.evaluate(dom, XPathConstants.STRING);
  58.105 +        
  58.106 +        assertEquals(arch, version, "bck2brwsr dependency is on more recent version");
  58.107 +    }
  58.108 +    
  58.109 +    @Test public void testNbActions() throws Exception {
  58.110 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  58.111 +        URL r = l.getResource("archetype-resources/nbactions.xml");
  58.112 +        assertNotNull(r, "Archetype nb file found");
  58.113 +        
  58.114 +        final XPathFactory fact = XPathFactory.newInstance();
  58.115 +        XPathExpression xp2 = fact.newXPath().compile(
  58.116 +            "//goal/text()"
  58.117 +        );
  58.118 +        
  58.119 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(r.openStream());
  58.120 +        NodeList goals = (NodeList) xp2.evaluate(dom, XPathConstants.NODESET);
  58.121 +        
  58.122 +        for (int i = 0; i < goals.getLength(); i++) {
  58.123 +            String s = goals.item(i).getTextContent();
  58.124 +            if (s.contains("apidesign")) {
  58.125 +                assertFalse(s.matches(".*apidesign.*[0-9].*"), "No numbers: " + s);
  58.126 +            }
  58.127 +        }
  58.128 +    }
  58.129 +
  58.130 +    static String findCurrentVersion() throws XPathExpressionException, IOException, ParserConfigurationException, SAXException, XPathFactoryConfigurationException {
  58.131 +        final ClassLoader l = ArchetypeVersionTest.class.getClassLoader();
  58.132 +        URL u = l.getResource("META-INF/maven/org.apidesign.bck2brwsr/knockout4j-archetype/pom.xml");
  58.133 +        assertNotNull(u, "Own pom found: " + System.getProperty("java.class.path"));
  58.134 +
  58.135 +        final XPathFactory fact = XPathFactory.newInstance();
  58.136 +        fact.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
  58.137 +
  58.138 +        XPathExpression xp = fact.newXPath().compile("project/version/text()");
  58.139 +        
  58.140 +        Document dom = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(u.openStream());
  58.141 +        return xp.evaluate(dom);
  58.142 +    }
  58.143 +}
    59.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    59.2 +++ b/ko/archetype-test/src/test/java/org/apidesign/bck2brwsr/ko/archetype/test/VerifyArchetypeTest.java	Mon Oct 07 14:20:58 2013 +0200
    59.3 @@ -0,0 +1,133 @@
    59.4 +/**
    59.5 + * Back 2 Browser Bytecode Translator
    59.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    59.7 + *
    59.8 + * This program is free software: you can redistribute it and/or modify
    59.9 + * it under the terms of the GNU General Public License as published by
   59.10 + * the Free Software Foundation, version 2 of the License.
   59.11 + *
   59.12 + * This program is distributed in the hope that it will be useful,
   59.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   59.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   59.15 + * GNU General Public License for more details.
   59.16 + *
   59.17 + * You should have received a copy of the GNU General Public License
   59.18 + * along with this program. Look for COPYING file in the top folder.
   59.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   59.20 + */
   59.21 +package org.apidesign.bck2brwsr.ko.archetype.test;
   59.22 +
   59.23 +import java.io.File;
   59.24 +import java.io.IOException;
   59.25 +import java.io.InputStream;
   59.26 +import java.util.Properties;
   59.27 +import java.util.zip.ZipEntry;
   59.28 +import java.util.zip.ZipFile;
   59.29 +import org.apache.maven.it.Verifier;
   59.30 +import org.testng.annotations.Test;
   59.31 +import static org.testng.Assert.*;
   59.32 +import org.testng.reporters.Files;
   59.33 +
   59.34 +/**
   59.35 + *
   59.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   59.37 + */
   59.38 +public class VerifyArchetypeTest {
   59.39 +    @Test public void fxBrwsrCompiles() throws Exception {
   59.40 +        final File dir = new File("target/tests/fxcompile/").getAbsoluteFile();
   59.41 +        generateFromArchetype(dir);
   59.42 +        
   59.43 +        File created = new File(dir, "o-a-test");
   59.44 +        assertTrue(created.isDirectory(), "Project created");
   59.45 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
   59.46 +        
   59.47 +        Verifier v = new Verifier(created.getAbsolutePath());
   59.48 +        v.executeGoal("verify");
   59.49 +        
   59.50 +        v.verifyErrorFreeLog();
   59.51 +        
   59.52 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
   59.53 +            if (l.contains("j2js")) {
   59.54 +                fail("No pre-compilaton:\n" + l);
   59.55 +            }
   59.56 +        }
   59.57 +        
   59.58 +        v.verifyTextInLog("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher");
   59.59 +        v.verifyTextInLog("fxcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-fxbrwsr.zip");
   59.60 +    }
   59.61 +    
   59.62 +    @Test public void bck2BrwsrCompiles() throws Exception {
   59.63 +        final File dir = new File("target/tests/b2bcompile/").getAbsoluteFile();
   59.64 +        generateFromArchetype(dir);
   59.65 +        
   59.66 +        File created = new File(dir, "o-a-test");
   59.67 +        assertTrue(created.isDirectory(), "Project created");
   59.68 +        assertTrue(new File(created, "pom.xml").isFile(), "Pom file is in there");
   59.69 +        
   59.70 +        Verifier v = new Verifier(created.getAbsolutePath());
   59.71 +        Properties sysProp = v.getSystemProperties();
   59.72 +        if (Boolean.getBoolean("java.awt.headless")) {
   59.73 +            sysProp.put("java.awt.headless", "true");
   59.74 +        }
   59.75 +        v.addCliOption("-Pbck2brwsr");
   59.76 +        v.executeGoal("verify");
   59.77 +        
   59.78 +        v.verifyErrorFreeLog();
   59.79 +        
   59.80 +        // does pre-compilation to JavaScript
   59.81 +        v.verifyTextInLog("j2js");
   59.82 +        // uses Bck2BrwsrLauncher
   59.83 +        v.verifyTextInLog("BaseHTTPLauncher showBrwsr");
   59.84 +        // building zip:
   59.85 +        v.verifyTextInLog("b2bcompile/o-a-test/target/o-a-test-1.0-SNAPSHOT-bck2brwsr.zip");
   59.86 +        
   59.87 +        for (String l : v.loadFile(v.getBasedir(), v.getLogFileName(), false)) {
   59.88 +            if (l.contains("fxbrwsr")) {
   59.89 +                fail("No fxbrwsr:\n" + l);
   59.90 +            }
   59.91 +        }
   59.92 +
   59.93 +        File zip = new File(new File(created, "target"), "o-a-test-1.0-SNAPSHOT-bck2brwsr.zip");
   59.94 +        assertTrue(zip.isFile(), "Zip file with website was created");
   59.95 +        
   59.96 +        ZipFile zf = new ZipFile(zip);
   59.97 +        final ZipEntry index = zf.getEntry("public_html/index.html");
   59.98 +        assertNotNull(index, "index.html found");
   59.99 +        
  59.100 +        String txt = readText(zf.getInputStream(index));
  59.101 +        final int beg = txt.indexOf("${");
  59.102 +        if (beg >= 0) {
  59.103 +            int end = txt.indexOf("}", beg);
  59.104 +            if (end < beg) {
  59.105 +                end = txt.length();
  59.106 +            }
  59.107 +            fail("No substitutions in index.html. Found: " + txt.substring(beg, end));
  59.108 +        }
  59.109 +    }
  59.110 +
  59.111 +    private Verifier generateFromArchetype(final File dir, String... params) throws Exception {
  59.112 +        Verifier v = new Verifier(dir.getAbsolutePath());
  59.113 +        v.setAutoclean(false);
  59.114 +        v.setLogFileName("generate.log");
  59.115 +        v.deleteDirectory("");
  59.116 +        dir.mkdirs();
  59.117 +        Properties sysProp = v.getSystemProperties();
  59.118 +        sysProp.put("groupId", "org.apidesign.test");
  59.119 +        sysProp.put("artifactId", "o-a-test");
  59.120 +        sysProp.put("package", "org.apidesign.test.oat");
  59.121 +        sysProp.put("archetypeGroupId", "org.apidesign.bck2brwsr");
  59.122 +        sysProp.put("archetypeArtifactId", "knockout4j-archetype");
  59.123 +        sysProp.put("archetypeVersion", ArchetypeVersionTest.findCurrentVersion());
  59.124 +        
  59.125 +        for (String p : params) {
  59.126 +            v.addCliOption(p);
  59.127 +        }
  59.128 +        v.executeGoal("archetype:generate");
  59.129 +        v.verifyErrorFreeLog();
  59.130 +        return v;
  59.131 +    }
  59.132 +    
  59.133 +    private static String readText(InputStream is) throws IOException {
  59.134 +        return Files.readFile(is);
  59.135 +    }
  59.136 +}
    60.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    60.2 +++ b/ko/archetype/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    60.3 @@ -0,0 +1,58 @@
    60.4 +<?xml version="1.0" encoding="UTF-8"?>
    60.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    60.6 +  <modelVersion>4.0.0</modelVersion>
    60.7 +  <parent>
    60.8 +    <artifactId>ko</artifactId>
    60.9 +    <groupId>org.apidesign.bck2brwsr</groupId>
   60.10 +    <version>0.9-SNAPSHOT</version>
   60.11 +  </parent>
   60.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   60.13 +  <artifactId>knockout4j-archetype</artifactId>
   60.14 +  <version>0.9-SNAPSHOT</version>
   60.15 +  <packaging>jar</packaging>
   60.16 +  <name>Knockout Bck2Brwsr Maven Archetype</name>
   60.17 +  <description>
   60.18 +      HTML page with Knockout.js bindings driven by application model
   60.19 +      written in Java. Use your favorite language to code. Use
   60.20 +      HTML as a lightweight rendering toolkit. Deploy using JavaFX or 
   60.21 +      bck2brwsr virtual machine.
   60.22 +  </description>
   60.23 +  <build>
   60.24 +      <resources>
   60.25 +          <resource>
   60.26 +            <directory>src/main/resources</directory>
   60.27 +            <filtering>true</filtering>
   60.28 +            <includes>
   60.29 +                <include>**/pom.xml</include>
   60.30 +            </includes>
   60.31 +          </resource>
   60.32 +          <resource>
   60.33 +            <directory>src/main/resources</directory>
   60.34 +            <filtering>false</filtering>
   60.35 +            <excludes>
   60.36 +                <exclude>**/pom.xml</exclude>
   60.37 +            </excludes>
   60.38 +          </resource>
   60.39 +      </resources>      
   60.40 +      <plugins>
   60.41 +          <plugin>
   60.42 +              <groupId>org.apache.maven.plugins</groupId>
   60.43 +              <artifactId>maven-compiler-plugin</artifactId>
   60.44 +              <version>2.3.2</version>
   60.45 +              <configuration>
   60.46 +                  <source>1.6</source>
   60.47 +                  <target>1.6</target>
   60.48 +              </configuration>
   60.49 +          </plugin>
   60.50 +          <plugin>
   60.51 +              <groupId>org.apache.maven.plugins</groupId>
   60.52 +              <artifactId>maven-resources-plugin</artifactId>
   60.53 +              <version>2.6</version>
   60.54 +              <configuration>
   60.55 +                  <escapeString>\</escapeString>
   60.56 +                  <target>1.6</target>
   60.57 +              </configuration>
   60.58 +          </plugin>
   60.59 +      </plugins>
   60.60 +  </build>
   60.61 +</project>
    61.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    61.2 +++ b/ko/archetype/src/main/java/org/apidesign/bck2brwsr/ko/archetype/package-info.java	Mon Oct 07 14:20:58 2013 +0200
    61.3 @@ -0,0 +1,18 @@
    61.4 +/**
    61.5 + * Back 2 Browser Bytecode Translator
    61.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    61.7 + *
    61.8 + * This program is free software: you can redistribute it and/or modify
    61.9 + * it under the terms of the GNU General Public License as published by
   61.10 + * the Free Software Foundation, version 2 of the License.
   61.11 + *
   61.12 + * This program is distributed in the hope that it will be useful,
   61.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   61.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   61.15 + * GNU General Public License for more details.
   61.16 + *
   61.17 + * You should have received a copy of the GNU General Public License
   61.18 + * along with this program. Look for COPYING file in the top folder.
   61.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   61.20 + */
   61.21 +package org.apidesign.bck2brwsr.ko.archetype;
    62.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    62.2 +++ b/ko/archetype/src/main/resources/META-INF/maven/archetype-metadata.xml	Mon Oct 07 14:20:58 2013 +0200
    62.3 @@ -0,0 +1,63 @@
    62.4 +<?xml version="1.0" encoding="UTF-8"?>
    62.5 +<!--
    62.6 +
    62.7 +    Back 2 Browser Bytecode Translator
    62.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    62.9 +
   62.10 +    This program is free software: you can redistribute it and/or modify
   62.11 +    it under the terms of the GNU General Public License as published by
   62.12 +    the Free Software Foundation, version 2 of the License.
   62.13 +
   62.14 +    This program is distributed in the hope that it will be useful,
   62.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
   62.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   62.17 +    GNU General Public License for more details.
   62.18 +
   62.19 +    You should have received a copy of the GNU General Public License
   62.20 +    along with this program. Look for COPYING file in the top folder.
   62.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
   62.22 +
   62.23 +-->
   62.24 +<archetype-descriptor name="FX/Bck2Brwsr Example">
   62.25 +  <fileSets>
   62.26 +    <fileSet filtered="true" packaged="true">
   62.27 +      <directory>src/main/java</directory>
   62.28 +      <includes>
   62.29 +        <include>**/*.java</include>
   62.30 +      </includes>
   62.31 +    </fileSet>
   62.32 +    <fileSet filtered="true" packaged="false">
   62.33 +      <directory>src/main/webapp/pages</directory>
   62.34 +      <includes>
   62.35 +        <include>**/*.xhtml</include>
   62.36 +        <include>**/*.html</include>
   62.37 +        <include>**/*.css</include>
   62.38 +      </includes>
   62.39 +    </fileSet>
   62.40 +    <fileSet filtered="true" packaged="true">
   62.41 +      <directory>src/test/java</directory>
   62.42 +      <includes>
   62.43 +        <include>**/*Test.java</include>
   62.44 +      </includes>
   62.45 +    </fileSet>
   62.46 +    <fileSet filtered="true" packaged="false">
   62.47 +      <directory>src/main/assembly</directory>
   62.48 +      <includes>
   62.49 +        <include>**/*.xml</include>
   62.50 +      </includes>
   62.51 +    </fileSet>
   62.52 +    <fileSet filtered="false" packaged="false">
   62.53 +      <directory></directory>
   62.54 +      <includes>
   62.55 +        <include>nbactions*.xml</include>
   62.56 +      </includes>
   62.57 +    </fileSet>
   62.58 +    <fileSet filtered="true" packaged="false">
   62.59 +      <directory>assembly</directory>
   62.60 +      <includes>
   62.61 +        <include>fxbrwsr-assembly.xml</include>
   62.62 +        <include>bck2brwsr-assembly.xml</include>
   62.63 +      </includes>
   62.64 +    </fileSet>
   62.65 +  </fileSets>    
   62.66 +</archetype-descriptor>
   62.67 \ No newline at end of file
    63.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    63.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-bck2brwsr.xml	Mon Oct 07 14:20:58 2013 +0200
    63.3 @@ -0,0 +1,14 @@
    63.4 +<?xml version="1.0" encoding="UTF-8"?>
    63.5 +<actions>
    63.6 +    <action>
    63.7 +        <actionName>run</actionName>
    63.8 +        <goals>
    63.9 +            <goal>package</goal>
   63.10 +            <goal>bck2brwsr:brwsr</goal>
   63.11 +        </goals>
   63.12 +        <properties>
   63.13 +            <skipTests>true</skipTests>
   63.14 +            <bck2brwsr.obfuscationlevel>NONE</bck2brwsr.obfuscationlevel>
   63.15 +        </properties>
   63.16 +    </action>
   63.17 +</actions>
    64.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    64.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions-fxbrwsr.xml	Mon Oct 07 14:20:58 2013 +0200
    64.3 @@ -0,0 +1,20 @@
    64.4 +<?xml version="1.0" encoding="UTF-8"?>
    64.5 +<actions>
    64.6 +    <action>
    64.7 +        <actionName>run</actionName>
    64.8 +        <goals>
    64.9 +            <goal>process-classes</goal>
   64.10 +            <goal>bck2brwsr:brwsr</goal>
   64.11 +        </goals>
   64.12 +    </action>
   64.13 +    <action>
   64.14 +        <actionName>debug</actionName>
   64.15 +        <goals>
   64.16 +            <goal>process-classes</goal>
   64.17 +            <goal>bck2brwsr:brwsr</goal>
   64.18 +        </goals>
   64.19 +        <properties>
   64.20 +            <jpda.listen>maven</jpda.listen>
   64.21 +        </properties>
   64.22 +    </action>
   64.23 +</actions>
    65.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    65.2 +++ b/ko/archetype/src/main/resources/archetype-resources/nbactions.xml	Mon Oct 07 14:20:58 2013 +0200
    65.3 @@ -0,0 +1,20 @@
    65.4 +<?xml version="1.0" encoding="UTF-8"?>
    65.5 +<actions>
    65.6 +    <action>
    65.7 +        <actionName>run</actionName>
    65.8 +        <goals>
    65.9 +            <goal>process-classes</goal>
   65.10 +            <goal>bck2brwsr:brwsr</goal>
   65.11 +        </goals>
   65.12 +    </action>
   65.13 +    <action>
   65.14 +        <actionName>debug</actionName>
   65.15 +        <goals>
   65.16 +            <goal>process-classes</goal>
   65.17 +            <goal>bck2brwsr:brwsr</goal>
   65.18 +        </goals>
   65.19 +        <properties>
   65.20 +            <jpda.listen>maven</jpda.listen>
   65.21 +        </properties>
   65.22 +    </action>
   65.23 +</actions>
    66.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    66.2 +++ b/ko/archetype/src/main/resources/archetype-resources/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    66.3 @@ -0,0 +1,267 @@
    66.4 +<?xml version="1.0"?>
    66.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    66.6 +  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    66.7 +  <modelVersion>4.0.0</modelVersion>
    66.8 +
    66.9 +  <groupId>\${groupId}</groupId>
   66.10 +  <artifactId>\${artifactId}</artifactId>
   66.11 +  <version>\${version}</version>
   66.12 +  <packaging>jar</packaging>
   66.13 +
   66.14 +  <name>\${artifactId}</name>
   66.15 +
   66.16 +  <repositories>
   66.17 +      <repository>
   66.18 +          <id>java.net</id>
   66.19 +          <name>Java.net</name>
   66.20 +          <url>https://maven.java.net/content/repositories/releases/</url>
   66.21 +          <snapshots>
   66.22 +              <enabled>true</enabled>
   66.23 +          </snapshots>
   66.24 +      </repository>
   66.25 +      <repository>
   66.26 +          <id>netbeans</id>
   66.27 +          <name>NetBeans</name>
   66.28 +          <url>http://bits.netbeans.org/maven2/</url>
   66.29 +      </repository>
   66.30 +  </repositories>
   66.31 +  <pluginRepositories>
   66.32 +      <pluginRepository>
   66.33 +          <id>java.net</id>
   66.34 +          <name>Java.net</name>
   66.35 +          <url>https://maven.java.net/content/repositories/releases/</url>
   66.36 +          <snapshots>
   66.37 +              <enabled>true</enabled>
   66.38 +          </snapshots>
   66.39 +      </pluginRepository>
   66.40 +  </pluginRepositories>
   66.41 +
   66.42 +  <properties>
   66.43 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   66.44 +    <net.java.html.version>${net.java.html.version}</net.java.html.version>
   66.45 +    <bck2brwsr.version>${project.version}</bck2brwsr.version>
   66.46 +    <bck2brwsr.launcher.version>${project.version}</bck2brwsr.launcher.version>
   66.47 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
   66.48 +    <brwsr.startpage>pages/index.html</brwsr.startpage>
   66.49 +  </properties>
   66.50 +  <build>
   66.51 +      <plugins>
   66.52 +          <plugin>
   66.53 +              <groupId>org.apidesign.bck2brwsr</groupId>
   66.54 +              <artifactId>bck2brwsr-maven-plugin</artifactId>
   66.55 +              <version>\${bck2brwsr.launcher.version}</version>
   66.56 +              <executions>
   66.57 +                  <execution>
   66.58 +                      <goals>
   66.59 +                          <goal>brwsr</goal>
   66.60 +                      </goals>
   66.61 +                  </execution>
   66.62 +              </executions>
   66.63 +              <configuration>
   66.64 +                  <directory>\${basedir}/src/main/webapp/</directory>
   66.65 +                  <startpage>${brwsr.startpage}</startpage>
   66.66 +                  <launcher>${brwsr}</launcher>
   66.67 +              </configuration>
   66.68 +          </plugin>
   66.69 +          <plugin>
   66.70 +              <groupId>org.apache.maven.plugins</groupId>
   66.71 +              <artifactId>maven-compiler-plugin</artifactId>
   66.72 +              <version>2.3.2</version>
   66.73 +              <configuration>
   66.74 +                  <source>1.7</source>
   66.75 +                  <target>1.7</target>
   66.76 +              </configuration>
   66.77 +          </plugin>
   66.78 +          <plugin>
   66.79 +              <groupId>org.apache.maven.plugins</groupId>
   66.80 +              <artifactId>maven-surefire-plugin</artifactId>
   66.81 +              <version>2.14.1</version>
   66.82 +              <configuration>
   66.83 +                  <systemPropertyVariables>
   66.84 +                      <vmtest.brwsrs>\${brwsr}</vmtest.brwsrs>
   66.85 +                  </systemPropertyVariables>
   66.86 +              </configuration>
   66.87 +          </plugin>
   66.88 +          <plugin>
   66.89 +              <groupId>org.apache.maven.plugins</groupId>
   66.90 +              <artifactId>maven-jar-plugin</artifactId>
   66.91 +              <version>2.4</version>
   66.92 +              <configuration>
   66.93 +                  <archive>
   66.94 +                      <manifest>
   66.95 +                          <addClasspath>true</addClasspath>
   66.96 +                          <classpathPrefix>lib/</classpathPrefix>
   66.97 +                      </manifest>
   66.98 +                  </archive>
   66.99 +              </configuration>
  66.100 +          </plugin>
  66.101 +          <plugin>
  66.102 +              <groupId>org.apache.maven.plugins</groupId>
  66.103 +              <artifactId>maven-deploy-plugin</artifactId>
  66.104 +              <version>2.7</version>
  66.105 +              <configuration>
  66.106 +                  <skip>true</skip>
  66.107 +              </configuration>
  66.108 +          </plugin>      
  66.109 +      </plugins>
  66.110 +  </build>
  66.111 +
  66.112 +  <dependencies>
  66.113 +    <dependency>
  66.114 +      <groupId>org.testng</groupId>
  66.115 +      <artifactId>testng</artifactId>
  66.116 +      <version>6.5.2</version>
  66.117 +      <scope>test</scope>
  66.118 +    </dependency>
  66.119 +    <dependency>
  66.120 +        <groupId>org.apidesign.bck2brwsr</groupId>
  66.121 +        <artifactId>launcher.http</artifactId>
  66.122 +        <version>\${bck2brwsr.launcher.version}</version>
  66.123 +        <scope>test</scope>
  66.124 +    </dependency>
  66.125 +    <dependency>
  66.126 +      <groupId>org.apidesign.bck2brwsr</groupId>
  66.127 +      <artifactId>vmtest</artifactId>
  66.128 +      <version>\${bck2brwsr.version}</version>
  66.129 +      <scope>test</scope>
  66.130 +    </dependency>
  66.131 +    <dependency>
  66.132 +      <groupId>org.apidesign.html</groupId>
  66.133 +      <artifactId>net.java.html.json</artifactId>
  66.134 +      <version>\${net.java.html.version}</version>
  66.135 +      <type>jar</type>
  66.136 +    </dependency>
  66.137 +  </dependencies>
  66.138 +  <profiles>
  66.139 +      <profile>
  66.140 +          <id>fxbrwsr</id>
  66.141 +          <activation>
  66.142 +              <activeByDefault>true</activeByDefault>
  66.143 +          </activation>
  66.144 +          <properties>
  66.145 +              <brwsr>fxbrwsr</brwsr>
  66.146 +          </properties>
  66.147 +          <build>
  66.148 +            <plugins>
  66.149 +                <plugin>
  66.150 +                    <groupId>org.apache.maven.plugins</groupId>
  66.151 +                    <artifactId>maven-jar-plugin</artifactId>
  66.152 +                    <version>2.4</version>
  66.153 +                    <configuration>
  66.154 +                        <archive>
  66.155 +                            <manifest>
  66.156 +                                <mainClass>org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher</mainClass>
  66.157 +                                <addClasspath>true</addClasspath>
  66.158 +                                <classpathPrefix>lib/</classpathPrefix>
  66.159 +                            </manifest>
  66.160 +                            <manifestEntries>
  66.161 +                                <StartPage>\${brwsr.startpage}</StartPage>
  66.162 +                            </manifestEntries>
  66.163 +                        </archive>
  66.164 +                    </configuration>
  66.165 +                </plugin>
  66.166 +                <plugin>
  66.167 +                    <artifactId>maven-assembly-plugin</artifactId>
  66.168 +                    <version>2.4</version>
  66.169 +                    <executions>
  66.170 +                        <execution>
  66.171 +                            <id>distro-assembly</id>
  66.172 +                            <phase>package</phase>
  66.173 +                            <goals>
  66.174 +                                <goal>single</goal>
  66.175 +                            </goals>
  66.176 +                            <configuration>
  66.177 +                                <descriptors>
  66.178 +                                    <descriptor>src/main/assembly/fxbrwsr.xml</descriptor>
  66.179 +                                </descriptors>
  66.180 +                            </configuration>
  66.181 +                        </execution>
  66.182 +                    </executions>                
  66.183 +                </plugin>      
  66.184 +            </plugins>
  66.185 +          </build>
  66.186 +          <dependencies>
  66.187 +              <dependency>
  66.188 +                  <groupId>org.apidesign.html</groupId>
  66.189 +                  <artifactId>ko-fx</artifactId>
  66.190 +                  <version>\${net.java.html.version}</version>
  66.191 +              </dependency>
  66.192 +              <dependency>
  66.193 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  66.194 +                  <artifactId>launcher.fx</artifactId>
  66.195 +                  <version>\${bck2brwsr.launcher.version}</version>
  66.196 +                  <scope>runtime</scope>
  66.197 +              </dependency>
  66.198 +          </dependencies>
  66.199 +      </profile>
  66.200 +      <profile>
  66.201 +          <id>bck2brwsr</id>
  66.202 +          <activation>
  66.203 +              <property>
  66.204 +                  <name>brwsr</name>
  66.205 +                  <value>bck2brwsr</value>
  66.206 +              </property>
  66.207 +          </activation>
  66.208 +          <build>
  66.209 +              <plugins>
  66.210 +                  <plugin>
  66.211 +                      <groupId>org.apidesign.bck2brwsr</groupId>
  66.212 +                      <artifactId>bck2brwsr-maven-plugin</artifactId>
  66.213 +                      <executions>
  66.214 +                          <execution>
  66.215 +                              <goals>
  66.216 +                                  <goal>j2js</goal>
  66.217 +                              </goals>
  66.218 +                          </execution>
  66.219 +                      </executions>
  66.220 +                      <configuration>
  66.221 +                          <javascript>\${project.build.directory}/bck2brwsr.js</javascript>
  66.222 +                          <obfuscation>\${bck2brwsr.obfuscationlevel}</obfuscation>
  66.223 +                      </configuration>
  66.224 +                  </plugin>
  66.225 +                  <plugin>
  66.226 +                      <groupId>org.apache.maven.plugins</groupId>
  66.227 +                      <artifactId>maven-compiler-plugin</artifactId>
  66.228 +                      <configuration>
  66.229 +                          <compilerArguments>
  66.230 +                              <bootclasspath>netbeans.ignore.jdk.bootclasspath</bootclasspath>
  66.231 +                          </compilerArguments>
  66.232 +                      </configuration>
  66.233 +                  </plugin>
  66.234 +                  <plugin>
  66.235 +                      <artifactId>maven-assembly-plugin</artifactId>
  66.236 +                      <version>2.4</version>
  66.237 +                      <executions>
  66.238 +                          <execution>
  66.239 +                              <id>distro-assembly</id>
  66.240 +                              <phase>package</phase>
  66.241 +                              <goals>
  66.242 +                                  <goal>single</goal>
  66.243 +                              </goals>
  66.244 +                              <configuration>
  66.245 +                                  <descriptors>
  66.246 +                                      <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
  66.247 +                                  </descriptors>
  66.248 +                              </configuration>
  66.249 +                          </execution>
  66.250 +                      </executions>                
  66.251 +                  </plugin>      
  66.252 +              </plugins>
  66.253 +          </build>
  66.254 +          <dependencies>
  66.255 +              <dependency>
  66.256 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  66.257 +                  <artifactId>emul</artifactId>
  66.258 +                  <version>\${bck2brwsr.version}</version>
  66.259 +                  <classifier>rt</classifier>
  66.260 +              </dependency>
  66.261 +              <dependency>
  66.262 +                  <groupId>org.apidesign.bck2brwsr</groupId>
  66.263 +                  <artifactId>ko-bck2brwsr</artifactId>
  66.264 +                  <version>\${bck2brwsr.version}</version>
  66.265 +                  <scope>runtime</scope>
  66.266 +              </dependency>
  66.267 +          </dependencies>
  66.268 +      </profile>
  66.269 +  </profiles>
  66.270 +</project>
    67.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    67.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/bck2brwsr.xml	Mon Oct 07 14:20:58 2013 +0200
    67.3 @@ -0,0 +1,48 @@
    67.4 +<?xml version="1.0"?>
    67.5 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    67.6 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    67.7 +  
    67.8 +  <id>bck2brwsr</id>
    67.9 +  <formats>
   67.10 +      <format>zip</format>
   67.11 +  </formats>
   67.12 +  <baseDirectory>public_html</baseDirectory>
   67.13 +  <dependencySets>
   67.14 +    <dependencySet>
   67.15 +        <useProjectArtifact>false</useProjectArtifact>
   67.16 +        <scope>runtime</scope>
   67.17 +        <outputDirectory>lib</outputDirectory>
   67.18 +        <includes>
   67.19 +            <include>*:jar</include>
   67.20 +            <include>*:rt</include>
   67.21 +        </includes>
   67.22 +    </dependencySet>
   67.23 +  </dependencySets> 
   67.24 +  <fileSets>
   67.25 +      <fileSet>
   67.26 +          <directory>${project.build.directory}/classes/${package.replace('.','/')}/</directory>
   67.27 +          <includes>
   67.28 +              <include>**/*</include>
   67.29 +          </includes>
   67.30 +          <excludes>
   67.31 +              <exclude>**/*.class</exclude>
   67.32 +          </excludes>
   67.33 +          <outputDirectory>/</outputDirectory>
   67.34 +      </fileSet>
   67.35 +      <fileSet>
   67.36 +          <directory>src/main/webapp/pages</directory>
   67.37 +          <outputDirectory>/</outputDirectory>
   67.38 +          <filtered>true</filtered>
   67.39 +      </fileSet>
   67.40 +  </fileSets>
   67.41 +  <files>
   67.42 +    <file>
   67.43 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   67.44 +      <outputDirectory>/</outputDirectory>
   67.45 +    </file>
   67.46 +    <file>
   67.47 +      <source>${project.build.directory}/bck2brwsr.js</source>
   67.48 +      <outputDirectory>/</outputDirectory>
   67.49 +    </file>
   67.50 +  </files>
   67.51 +</assembly>
   67.52 \ No newline at end of file
    68.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    68.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/assembly/fxbrwsr.xml	Mon Oct 07 14:20:58 2013 +0200
    68.3 @@ -0,0 +1,33 @@
    68.4 +<?xml version="1.0"?>
    68.5 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    68.6 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    68.7 +  
    68.8 +  <id>fxbrwsr</id>
    68.9 +  <formats>
   68.10 +      <format>zip</format>
   68.11 +  </formats>
   68.12 +  <baseDirectory>${project.build.finalName}-fxbrwsr</baseDirectory>
   68.13 +  <dependencySets>
   68.14 +    <dependencySet>
   68.15 +        <useProjectArtifact>false</useProjectArtifact>
   68.16 +        <scope>runtime</scope>
   68.17 +        <outputDirectory>lib</outputDirectory>
   68.18 +    </dependencySet>
   68.19 +  </dependencySets> 
   68.20 +  <files>
   68.21 +    <file>
   68.22 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
   68.23 +      <outputDirectory>/</outputDirectory>
   68.24 +    </file>
   68.25 +  </files>
   68.26 +  <fileSets>
   68.27 +    <fileSet>
   68.28 +       <directory>src/main/webapp/</directory>
   68.29 +       <outputDirectory>/</outputDirectory>
   68.30 +       <includes>
   68.31 +          <include>pages/**</include>
   68.32 +       </includes>
   68.33 +       <filtered>true</filtered>
   68.34 +    </fileSet>
   68.35 +  </fileSets>
   68.36 +</assembly>
   68.37 \ No newline at end of file
    69.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    69.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/DataModel.java	Mon Oct 07 14:20:58 2013 +0200
    69.3 @@ -0,0 +1,31 @@
    69.4 +package ${package};
    69.5 +
    69.6 +import net.java.html.json.ComputedProperty;
    69.7 +import net.java.html.json.Function;
    69.8 +import net.java.html.json.Model;
    69.9 +import net.java.html.json.Property;
   69.10 +
   69.11 +/** Model annotation generates class Data with 
   69.12 + * one message property, boolean property and read only words property
   69.13 + */
   69.14 +@Model(className = "Data", properties = {
   69.15 +    @Property(name = "message", type = String.class),
   69.16 +    @Property(name = "on", type = boolean.class)
   69.17 +})
   69.18 +final class DataModel {
   69.19 +    @ComputedProperty static java.util.List<String> words(String message) {
   69.20 +        String[] arr = new String[6];
   69.21 +        String[] words = message == null ? new String[0] : message.split(" ", 6);
   69.22 +        for (int i = 0; i < 6; i++) {
   69.23 +            arr[i] = words.length > i ? words[i] : "!";
   69.24 +        }
   69.25 +        return java.util.Arrays.asList(arr);
   69.26 +    }
   69.27 +    
   69.28 +    @Function static void turnOn(Data model) {
   69.29 +        model.setOn(true);
   69.30 +    }
   69.31 +    @Function static void turnOff(Data model) {
   69.32 +        model.setOn(false);
   69.33 +    }
   69.34 +}
    70.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    70.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/java/Main.java	Mon Oct 07 14:20:58 2013 +0200
    70.3 @@ -0,0 +1,15 @@
    70.4 +package ${package};
    70.5 +
    70.6 +public final class Main {
    70.7 +    private Main() {
    70.8 +    }
    70.9 +    
   70.10 +    /**
   70.11 +     * Called when the page is ready.
   70.12 +     */
   70.13 +    static {
   70.14 +        Data d = new Data();
   70.15 +        d.setMessage("Hello World from HTML and Java!");
   70.16 +        d.applyBindings();
   70.17 +    }
   70.18 +}
    71.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    71.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/main/webapp/pages/index.html	Mon Oct 07 14:20:58 2013 +0200
    71.3 @@ -0,0 +1,63 @@
    71.4 +<!DOCTYPE html>
    71.5 +<html>
    71.6 +    <head>
    71.7 +        <title></title>
    71.8 +        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    71.9 +
   71.10 +        <style type="text/css">
   71.11 +            @-webkit-keyframes spin {
   71.12 +                0% { -webkit-transform: rotate(0deg); }
   71.13 +                100% { -webkit-transform: rotate(360deg); }
   71.14 +            }
   71.15 +
   71.16 +            .rotate {
   71.17 +                -webkit-animation-name: spin;
   71.18 +                -webkit-animation-duration: 3s;
   71.19 +                -webkit-animation-iteration-count: infinite;
   71.20 +                -webkit-animation-direction: alternate;
   71.21 +            }
   71.22 +
   71.23 +            #scene {
   71.24 +                position: relative;
   71.25 +                top: 60px;
   71.26 +                text-align: center;
   71.27 +            }
   71.28 +            
   71.29 +            #words span {
   71.30 +                border: 1px solid #ccc;
   71.31 +                background: rgba(255,255,155,0.8);
   71.32 +                text-align: center;
   71.33 +                font-size: 30px;                
   71.34 +                -webkit-box-shadow: inset 0 0 40px rgba(0,0,0,0.4);
   71.35 +                position: absolute;
   71.36 +            }
   71.37 +
   71.38 +            #words span:nth-child(1) { left: 45%; top: 0px; }
   71.39 +            #words span:nth-child(2) { left: 25%; top: 100px; }
   71.40 +            #words span:nth-child(3) { left: 65%; top: 100px; }
   71.41 +            #words span:nth-child(4) { left: 10%; top: 200px; }
   71.42 +            #words span:nth-child(5) { left: 45%; top: 200px; }
   71.43 +            #words span:nth-child(6) { left: 80%; top: 200px; }
   71.44 +            
   71.45 +        </style>
   71.46 +
   71.47 +    </head>
   71.48 +    <body>
   71.49 +        <h1>Words Demo</h1>
   71.50 +        <input data-bind="value: message, valueUpdate: 'afterkeydown'" size="80">
   71.51 +        <br>
   71.52 +        <button data-bind="enable: !on(), click: $root.turnOn">Start</button>
   71.53 +        <button data-bind="enable: on, click: $root.turnOff">Stop</button>
   71.54 +
   71.55 +        <div id="scene">
   71.56 +            <span id="words" data-bind="foreach: words">
   71.57 +                <span data-bind="text: $data, css: { 'rotate' : $root.on } "></span>
   71.58 +            </span>
   71.59 +        </div>
   71.60 +        <script type="text/javascript" src="bck2brwsr.js"></script>
   71.61 +        <script>
   71.62 +            var vm = bck2brwsr('${project.build.finalName}.jar');
   71.63 +            vm.loadClass('${package}.Main');
   71.64 +        </script>
   71.65 +    </body>
   71.66 +</html>
    72.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    72.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/DataModelTest.java	Mon Oct 07 14:20:58 2013 +0200
    72.3 @@ -0,0 +1,16 @@
    72.4 +package ${package};
    72.5 +
    72.6 +import static org.testng.Assert.*;
    72.7 +import org.testng.annotations.Test;
    72.8 +
    72.9 +public class DataModelTest {
   72.10 +    @Test public void areHelloWorldTwoWords() {
   72.11 +        Data model = new Data();
   72.12 +        model.setMessage("Hello World!");
   72.13 +        
   72.14 +        java.util.List<String> arr = model.getWords();
   72.15 +        assertEquals(arr.size(), 6, "Six words always");
   72.16 +        assertEquals("Hello", arr.get(0), "Hello is the first word");
   72.17 +        assertEquals("World!", arr.get(1), "World is the second word");
   72.18 +    }
   72.19 +}
    73.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    73.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java	Mon Oct 07 14:20:58 2013 +0200
    73.3 @@ -0,0 +1,38 @@
    73.4 +package ${package};
    73.5 +
    73.6 +import org.apidesign.bck2brwsr.vmtest.Compare;
    73.7 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    73.8 +import org.testng.annotations.Factory;
    73.9 +
   73.10 +/** Bck2brwsr cares about compatibility with real Java. Whatever API is
   73.11 + * supported by bck2brwsr, it needs to behave the same way as when running
   73.12 + * in HotSpot VM. 
   73.13 + * <p>
   73.14 + * There can be bugs, however. To help us fix them, we kindly ask you to 
   73.15 + * write an "inconsistency" test. A test that compares behavior of the API
   73.16 + * between real VM and bck2brwsr VM. This class is skeleton of such test.
   73.17 + */
   73.18 +public class InconsistencyTest {
   73.19 +    /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
   73.20 +     * Make calls to an API that behaves strangely, return some result at
   73.21 +     * the end. No need to use any <code>assert</code>.
   73.22 +     * 
   73.23 +     * @return value to compare between HotSpot and bck2brwsr
   73.24 +     */
   73.25 +    @Compare
   73.26 +    public int checkStringHashCode() throws Exception {
   73.27 +        return "Is string hashCode the same?".hashCode();
   73.28 +    }
   73.29 +
   73.30 +    /** Factory method that creates a three tests for each method annotated with
   73.31 +     * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
   73.32 +     * HotSpot, one in Rhino and the last one compares the results.
   73.33 +     * 
   73.34 +     * @see org.apidesign.bck2brwsr.vmtest.VMTest
   73.35 +     */
   73.36 +    @Factory
   73.37 +    public static Object[] create() {
   73.38 +        return VMTest.create(InconsistencyTest.class);
   73.39 +    }
   73.40 +    
   73.41 +}
    74.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    74.2 +++ b/ko/archetype/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java	Mon Oct 07 14:20:58 2013 +0200
    74.3 @@ -0,0 +1,31 @@
    74.4 +package ${package};
    74.5 +
    74.6 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    74.7 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
    74.8 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    74.9 +import org.testng.annotations.Factory;
   74.10 +
   74.11 +/** Sometimes it is useful to run tests inside of the real browser. 
   74.12 + * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
   74.13 + * and that is it. If your code references elements on the HTML page,
   74.14 + * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
   74.15 + * will be made available on the page before your test starts.
   74.16 + */
   74.17 +public class IntegrationTest {
   74.18 +    
   74.19 +    /** Write to testing code here. Use <code>assert</code> (but not TestNG's
   74.20 +     * Assert, as TestNG is not compiled with target 1.6 yet).
   74.21 +     */
   74.22 +    @HtmlFragment(
   74.23 +        "<h1>Put this snippet on the HTML page</h1>\n"
   74.24 +    )
   74.25 +    @BrwsrTest
   74.26 +    public void runThisTestInABrowser() {
   74.27 +    }
   74.28 +
   74.29 +    @Factory
   74.30 +    public static Object[] create() {
   74.31 +        return VMTest.create(IntegrationTest.class);
   74.32 +    }
   74.33 +    
   74.34 +}
    75.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    75.2 +++ b/ko/bck2brwsr/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    75.3 @@ -0,0 +1,102 @@
    75.4 +<?xml version="1.0"?>
    75.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    75.6 +  <modelVersion>4.0.0</modelVersion>
    75.7 +  <parent>
    75.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    75.9 +    <artifactId>ko</artifactId>
   75.10 +    <version>0.9-SNAPSHOT</version>
   75.11 +  </parent>
   75.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   75.13 +  <artifactId>ko-bck2brwsr</artifactId>
   75.14 +  <version>0.9-SNAPSHOT</version>
   75.15 +  <name>Knockout.b2b</name>
   75.16 +  <url>http://maven.apache.org</url>
   75.17 +  <build>
   75.18 +      <plugins>
   75.19 +          <plugin>
   75.20 +              <groupId>org.apache.maven.plugins</groupId>
   75.21 +              <artifactId>maven-compiler-plugin</artifactId>
   75.22 +              <version>2.3.2</version>
   75.23 +              <configuration>
   75.24 +                  <source>1.7</source>
   75.25 +                  <target>1.7</target>
   75.26 +              </configuration>
   75.27 +          </plugin>
   75.28 +          <plugin>
   75.29 +              <groupId>org.apache.maven.plugins</groupId>
   75.30 +              <artifactId>maven-javadoc-plugin</artifactId>
   75.31 +              <configuration>
   75.32 +                  <skip>false</skip>
   75.33 +              </configuration>
   75.34 +          </plugin>
   75.35 +      </plugins>
   75.36 +  </build>
   75.37 +  <dependencies>
   75.38 +    <dependency>
   75.39 +      <groupId>org.testng</groupId>
   75.40 +      <artifactId>testng</artifactId>
   75.41 +      <scope>test</scope>
   75.42 +      <exclusions>
   75.43 +        <exclusion>
   75.44 +          <artifactId>junit</artifactId>
   75.45 +          <groupId>junit</groupId>
   75.46 +        </exclusion>
   75.47 +      </exclusions>
   75.48 +    </dependency>
   75.49 +    <dependency>
   75.50 +      <groupId>org.netbeans.api</groupId>
   75.51 +      <artifactId>org-openide-util-lookup</artifactId>
   75.52 +      <scope>provided</scope>
   75.53 +    </dependency>
   75.54 +    <dependency>
   75.55 +      <groupId>org.apidesign.bck2brwsr</groupId>
   75.56 +      <artifactId>emul</artifactId>
   75.57 +      <version>${project.version}</version>
   75.58 +      <classifier>rt</classifier>
   75.59 +      <type>jar</type>
   75.60 +      <scope>compile</scope>
   75.61 +    </dependency>
   75.62 +    <dependency>
   75.63 +      <groupId>org.apidesign.bck2brwsr</groupId>
   75.64 +      <artifactId>vm4brwsr</artifactId>
   75.65 +      <version>${project.version}</version>
   75.66 +      <type>jar</type>
   75.67 +      <scope>test</scope>
   75.68 +    </dependency>
   75.69 +    <dependency>
   75.70 +      <groupId>org.apidesign.bck2brwsr</groupId>
   75.71 +      <artifactId>vmtest</artifactId>
   75.72 +      <version>${project.version}</version>
   75.73 +      <scope>test</scope>
   75.74 +    </dependency>
   75.75 +    <dependency>
   75.76 +      <groupId>org.apidesign.bck2brwsr</groupId>
   75.77 +      <artifactId>launcher.http</artifactId>
   75.78 +      <version>${project.version}</version>
   75.79 +      <scope>test</scope>
   75.80 +    </dependency>
   75.81 +    <dependency>
   75.82 +      <groupId>org.apidesign.html</groupId>
   75.83 +      <artifactId>net.java.html.json</artifactId>
   75.84 +      <version>${net.java.html.version}</version>
   75.85 +    </dependency>
   75.86 +    <dependency>
   75.87 +      <groupId>org.apidesign.html</groupId>
   75.88 +      <artifactId>net.java.html.json.tck</artifactId>
   75.89 +      <version>${net.java.html.version}</version>
   75.90 +      <scope>test</scope>
   75.91 +    </dependency>
   75.92 +    <dependency>
   75.93 +      <groupId>org.apidesign.bck2brwsr</groupId>
   75.94 +      <artifactId>core</artifactId>
   75.95 +      <version>${project.version}</version>
   75.96 +      <type>jar</type>
   75.97 +    </dependency>
   75.98 +    <dependency>
   75.99 +      <groupId>org.apidesign.html</groupId>
  75.100 +      <artifactId>net.java.html.boot</artifactId>
  75.101 +      <version>0.5</version>
  75.102 +      <type>jar</type>
  75.103 +    </dependency>
  75.104 +  </dependencies>
  75.105 +</project>
    76.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    76.2 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/bck2brwsr/ko2brwsr/BrwsrCtxImpl.java	Mon Oct 07 14:20:58 2013 +0200
    76.3 @@ -0,0 +1,166 @@
    76.4 +/**
    76.5 + * Back 2 Browser Bytecode Translator
    76.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    76.7 + *
    76.8 + * This program is free software: you can redistribute it and/or modify
    76.9 + * it under the terms of the GNU General Public License as published by
   76.10 + * the Free Software Foundation, version 2 of the License.
   76.11 + *
   76.12 + * This program is distributed in the hope that it will be useful,
   76.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   76.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   76.15 + * GNU General Public License for more details.
   76.16 + *
   76.17 + * You should have received a copy of the GNU General Public License
   76.18 + * along with this program. Look for COPYING file in the top folder.
   76.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   76.20 + */
   76.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   76.22 +
   76.23 +import java.io.ByteArrayOutputStream;
   76.24 +import java.io.IOException;
   76.25 +import java.io.InputStream;
   76.26 +import java.io.InputStreamReader;
   76.27 +import org.apidesign.html.json.spi.FunctionBinding;
   76.28 +import org.apidesign.html.json.spi.JSONCall;
   76.29 +import org.apidesign.html.json.spi.PropertyBinding;
   76.30 +import org.apidesign.html.json.spi.Technology;
   76.31 +import org.apidesign.html.json.spi.Transfer;
   76.32 +import org.apidesign.html.json.spi.WSTransfer;
   76.33 +
   76.34 +/**
   76.35 + *
   76.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   76.37 + */
   76.38 +final class BrwsrCtxImpl implements Technology<Object>, Transfer, WSTransfer<LoadWS> {
   76.39 +    private BrwsrCtxImpl() {}
   76.40 +    
   76.41 +    public static final BrwsrCtxImpl DEFAULT = new BrwsrCtxImpl();
   76.42 +    
   76.43 +    @Override
   76.44 +    public void extract(Object obj, String[] props, Object[] values) {
   76.45 +        ConvertTypes.extractJSON(obj, props, values);
   76.46 +    }
   76.47 +
   76.48 +    @Override
   76.49 +    public void loadJSON(final JSONCall call) {
   76.50 +        class R implements Runnable {
   76.51 +            final boolean success;
   76.52 +
   76.53 +            public R(boolean success) {
   76.54 +                this.success = success;
   76.55 +            }
   76.56 +            
   76.57 +            Object[] arr = { null };
   76.58 +            @Override
   76.59 +            public void run() {
   76.60 +                if (success) {
   76.61 +                    call.notifySuccess(arr[0]);
   76.62 +                } else {
   76.63 +                    Throwable t;
   76.64 +                    if (arr[0] instanceof Throwable) {
   76.65 +                        t = (Throwable) arr[0];
   76.66 +                    } else {
   76.67 +                        if (arr[0] == null) {
   76.68 +                            t = new IOException();
   76.69 +                        } else {
   76.70 +                            t = new IOException(arr[0].toString());
   76.71 +                        }
   76.72 +                    }
   76.73 +                    call.notifyError(t);
   76.74 +                }
   76.75 +            }
   76.76 +        }
   76.77 +        R success = new R(true);
   76.78 +        R failure = new R(false);
   76.79 +        if (call.isJSONP()) {
   76.80 +            String me = ConvertTypes.createJSONP(success.arr, success);
   76.81 +            ConvertTypes.loadJSONP(call.composeURL(me), me);
   76.82 +        } else {
   76.83 +            String data = null;
   76.84 +            if (call.isDoOutput()) {
   76.85 +                try {
   76.86 +                    ByteArrayOutputStream bos = new ByteArrayOutputStream();
   76.87 +                    call.writeData(bos);
   76.88 +                    data = new String(bos.toByteArray(), "UTF-8");
   76.89 +                } catch (IOException ex) {
   76.90 +                    call.notifyError(ex);
   76.91 +                }
   76.92 +            }
   76.93 +            ConvertTypes.loadJSON(call.composeURL(null), success.arr, success, failure, call.getMethod(), data);
   76.94 +        }
   76.95 +    }
   76.96 +
   76.97 +    @Override
   76.98 +    public Object wrapModel(Object model) {
   76.99 +        return model;
  76.100 +    }
  76.101 +
  76.102 +    @Override
  76.103 +    public void bind(PropertyBinding b, Object model, Object data) {
  76.104 +        Knockout.bind(data, b, b.getPropertyName(), 
  76.105 +            "getValue__Ljava_lang_Object_2", 
  76.106 +            b.isReadOnly() ? null : "setValue__VLjava_lang_Object_2", 
  76.107 +            false, false
  76.108 +        );
  76.109 +    }
  76.110 +
  76.111 +    @Override
  76.112 +    public void valueHasMutated(Object data, String propertyName) {
  76.113 +        Knockout.valueHasMutated(data, propertyName);
  76.114 +    }
  76.115 +
  76.116 +    @Override
  76.117 +    public void expose(FunctionBinding fb, Object model, Object d) {
  76.118 +        Knockout.expose(d, fb, fb.getFunctionName(), "call__VLjava_lang_Object_2Ljava_lang_Object_2");
  76.119 +    }
  76.120 +
  76.121 +    @Override
  76.122 +    public void applyBindings(Object data) {
  76.123 +        Knockout.applyBindings(data);
  76.124 +    }
  76.125 +
  76.126 +    @Override
  76.127 +    public Object wrapArray(Object[] arr) {
  76.128 +        return arr;
  76.129 +    }
  76.130 +
  76.131 +    @Override
  76.132 +    public <M> M toModel(Class<M> modelClass, Object data) {
  76.133 +        return modelClass.cast(data);
  76.134 +    }
  76.135 +
  76.136 +    @Override
  76.137 +    public Object toJSON(InputStream is) throws IOException {
  76.138 +        StringBuilder sb = new StringBuilder();
  76.139 +        InputStreamReader r = new InputStreamReader(is);
  76.140 +        for (;;) {
  76.141 +            int ch = r.read();
  76.142 +            if (ch == -1) {
  76.143 +                break;
  76.144 +            }
  76.145 +            sb.append((char)ch);
  76.146 +        }
  76.147 +        return ConvertTypes.parse(sb.toString());
  76.148 +    }
  76.149 +
  76.150 +    @Override
  76.151 +    public void runSafe(Runnable r) {
  76.152 +        r.run();
  76.153 +    }
  76.154 +
  76.155 +    @Override
  76.156 +    public LoadWS open(String url, JSONCall callback) {
  76.157 +        return new LoadWS(callback, url);
  76.158 +    }
  76.159 +
  76.160 +    @Override
  76.161 +    public void send(LoadWS socket, JSONCall data) {
  76.162 +        socket.send(data);
  76.163 +    }
  76.164 +
  76.165 +    @Override
  76.166 +    public void close(LoadWS socket) {
  76.167 +        socket.close();
  76.168 +    }
  76.169 +}
    77.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    77.2 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/bck2brwsr/ko2brwsr/BrwsrCtxPrvdr.java	Mon Oct 07 14:20:58 2013 +0200
    77.3 @@ -0,0 +1,53 @@
    77.4 +/**
    77.5 + * Back 2 Browser Bytecode Translator
    77.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    77.7 + *
    77.8 + * This program is free software: you can redistribute it and/or modify
    77.9 + * it under the terms of the GNU General Public License as published by
   77.10 + * the Free Software Foundation, version 2 of the License.
   77.11 + *
   77.12 + * This program is distributed in the hope that it will be useful,
   77.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   77.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   77.15 + * GNU General Public License for more details.
   77.16 + *
   77.17 + * You should have received a copy of the GNU General Public License
   77.18 + * along with this program. Look for COPYING file in the top folder.
   77.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   77.20 + */
   77.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   77.22 +
   77.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   77.24 +import org.apidesign.html.context.spi.Contexts;
   77.25 +import org.apidesign.html.json.spi.Technology;
   77.26 +import org.apidesign.html.json.spi.Transfer;
   77.27 +import org.apidesign.html.json.spi.WSTransfer;
   77.28 +import org.openide.util.lookup.ServiceProvider;
   77.29 +
   77.30 +/** This is an implementation package - just
   77.31 + * include its JAR on classpath and use official {@link Context} API
   77.32 + * to access the functionality.
   77.33 + * <p>
   77.34 + * Provides binding between models and <a href="http://bck2brwsr.apidesign.org">
   77.35 + * Bck2Brwsr</a> VM.
   77.36 + * Registers {@link ContextProvider}, so {@link ServiceLoader} can find it.
   77.37 + *
   77.38 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   77.39 + */
   77.40 +@ServiceProvider(service = Contexts.Provider.class)
   77.41 +public final class BrwsrCtxPrvdr implements Contexts.Provider {
   77.42 +
   77.43 +    @Override
   77.44 +    public void fillContext(Contexts.Builder context, Class<?> requestor) {
   77.45 +        if (bck2BrwsrVM()) {
   77.46 +            context.register(Technology.class, BrwsrCtxImpl.DEFAULT, 50).
   77.47 +            register(Transfer.class, BrwsrCtxImpl.DEFAULT, 50).
   77.48 +            register(WSTransfer.class, BrwsrCtxImpl.DEFAULT, 50);
   77.49 +        }
   77.50 +    }
   77.51 +    
   77.52 +    @JavaScriptBody(args = {  }, body = "return true;")
   77.53 +    private static boolean bck2BrwsrVM() {
   77.54 +        return false;
   77.55 +    }
   77.56 +}
    78.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    78.2 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/bck2brwsr/ko2brwsr/ConvertTypes.java	Mon Oct 07 14:20:58 2013 +0200
    78.3 @@ -0,0 +1,157 @@
    78.4 +/**
    78.5 + * Back 2 Browser Bytecode Translator
    78.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    78.7 + *
    78.8 + * This program is free software: you can redistribute it and/or modify
    78.9 + * it under the terms of the GNU General Public License as published by
   78.10 + * the Free Software Foundation, version 2 of the License.
   78.11 + *
   78.12 + * This program is distributed in the hope that it will be useful,
   78.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   78.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   78.15 + * GNU General Public License for more details.
   78.16 + *
   78.17 + * You should have received a copy of the GNU General Public License
   78.18 + * along with this program. Look for COPYING file in the top folder.
   78.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   78.20 + */
   78.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   78.22 +
   78.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   78.24 +
   78.25 +/**
   78.26 + *
   78.27 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   78.28 + */
   78.29 +final class ConvertTypes {
   78.30 +    ConvertTypes() {
   78.31 +    }
   78.32 +    
   78.33 +    public static String toString(Object object, String property) {
   78.34 +        Object ret = getProperty(object, property);
   78.35 +        return ret == null ? null : ret.toString();
   78.36 +    }
   78.37 +
   78.38 +    public static double toDouble(Object object, String property) {
   78.39 +        Object ret = getProperty(object, property);
   78.40 +        return ret instanceof Number ? ((Number)ret).doubleValue() : Double.NaN;
   78.41 +    }
   78.42 +
   78.43 +    public static int toInt(Object object, String property) {
   78.44 +        Object ret = getProperty(object, property);
   78.45 +        return ret instanceof Number ? ((Number)ret).intValue() : Integer.MIN_VALUE;
   78.46 +    }
   78.47 +
   78.48 +    public static <T> T toModel(Class<T> modelClass, Object object, String property) {
   78.49 +        Object ret = getProperty(object, property);
   78.50 +        if (ret == null || modelClass.isInstance(ret)) {
   78.51 +            return modelClass.cast(ret);
   78.52 +        }
   78.53 +        throw new IllegalStateException("Value " + ret + " is not of type " + modelClass);
   78.54 +    }
   78.55 +    
   78.56 +    public static String toJSON(Object value) {
   78.57 +        if (value == null) {
   78.58 +            return "null";
   78.59 +        }
   78.60 +        if (value instanceof Enum) {
   78.61 +            value = value.toString();
   78.62 +        }
   78.63 +        if (value instanceof String) {
   78.64 +            return '"' + 
   78.65 +                ((String)value).
   78.66 +                    replace("\"", "\\\"").
   78.67 +                    replace("\n", "\\n").
   78.68 +                    replace("\r", "\\r").
   78.69 +                    replace("\t", "\\t")
   78.70 +                + '"';
   78.71 +        }
   78.72 +        return value.toString();
   78.73 +    }
   78.74 +    
   78.75 +    @JavaScriptBody(args = { "object", "property" },
   78.76 +        body = 
   78.77 +          "if (property === null) return object;\n"
   78.78 +        + "if (object === null) return null;\n"
   78.79 +        + "var p = object[property]; return p ? p : null;"
   78.80 +    )
   78.81 +    private static Object getProperty(Object object, String property) {
   78.82 +        return null;
   78.83 +    }
   78.84 +    
   78.85 +    public static String createJSONP(Object[] jsonResult, Runnable whenDone) {
   78.86 +        int h = whenDone.hashCode();
   78.87 +        String name;
   78.88 +        for (;;) {
   78.89 +            name = "jsonp" + Integer.toHexString(h);
   78.90 +            if (defineIfUnused(name, jsonResult, whenDone)) {
   78.91 +                return name;
   78.92 +            }
   78.93 +            h++;
   78.94 +        }
   78.95 +    }
   78.96 +
   78.97 +    @JavaScriptBody(args = { "name", "arr", "run" }, body = 
   78.98 +        "if (window[name]) return false;\n "
   78.99 +      + "window[name] = function(data) {\n "
  78.100 +      + "  delete window[name];\n"
  78.101 +      + "  var el = window.document.getElementById(name);\n"
  78.102 +      + "  el.parentNode.removeChild(el);\n"
  78.103 +      + "  arr[0] = data;\n"
  78.104 +      + "  run.run__V();\n"
  78.105 +      + "};\n"
  78.106 +      + "return true;\n"
  78.107 +    )
  78.108 +    private static boolean defineIfUnused(String name, Object[] arr, Runnable run) {
  78.109 +        return true;
  78.110 +    }
  78.111 +    
  78.112 +    @JavaScriptBody(args = { "s" }, body = "return eval('(' + s + ')');")
  78.113 +    static Object parse(String s) {
  78.114 +        return s;
  78.115 +    }
  78.116 +    
  78.117 +    @JavaScriptBody(args = { "url", "arr", "callback", "onError", "method", "data" }, body = ""
  78.118 +        + "var request = new XMLHttpRequest();\n"
  78.119 +        + "if (!method) method = 'GET';\n"
  78.120 +        + "request.open(method, url, true);\n"
  78.121 +        + "request.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n"
  78.122 +        + "request.onreadystatechange = function() {\n"
  78.123 +        + "  if (this.readyState!==4) return;\n"
  78.124 +        + "  try {\n"
  78.125 +        + "    arr[0] = eval('(' + this.response + ')');\n"
  78.126 +        + "  } catch (error) {;\n"
  78.127 +        + "    arr[0] = this.response;\n"
  78.128 +        + "  }\n"
  78.129 +        + "  callback.run__V();\n"
  78.130 +        + "};\n"
  78.131 +        + "request.onerror = function (e) {\n"
  78.132 +        + "  arr[0] = e; onError.run__V();\n"
  78.133 +        + "}\n"
  78.134 +        + "if (data) request.send(data);"
  78.135 +        + "else request.send();"
  78.136 +    )
  78.137 +    static void loadJSON(
  78.138 +        String url, Object[] jsonResult, Runnable whenDone, Runnable whenErr, String method, String data
  78.139 +    ) {
  78.140 +    }
  78.141 +    
  78.142 +    @JavaScriptBody(args = { "url", "jsonp" }, body = 
  78.143 +        "var scrpt = window.document.createElement('script');\n "
  78.144 +        + "scrpt.setAttribute('src', url);\n "
  78.145 +        + "scrpt.setAttribute('id', jsonp);\n "
  78.146 +        + "scrpt.setAttribute('type', 'text/javascript');\n "
  78.147 +        + "var body = document.getElementsByTagName('body')[0];\n "
  78.148 +        + "body.appendChild(scrpt);\n"
  78.149 +    )
  78.150 +    static void loadJSONP(String url, String jsonp) {
  78.151 +        
  78.152 +    }
  78.153 +    
  78.154 +    public static void extractJSON(Object jsonObject, String[] props, Object[] values) {
  78.155 +        for (int i = 0; i < props.length; i++) {
  78.156 +            values[i] = getProperty(jsonObject, props[i]);
  78.157 +        }
  78.158 +    }
  78.159 +    
  78.160 +}
    79.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    79.2 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/bck2brwsr/ko2brwsr/Knockout.java	Mon Oct 07 14:20:58 2013 +0200
    79.3 @@ -0,0 +1,131 @@
    79.4 +/**
    79.5 + * Back 2 Browser Bytecode Translator
    79.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    79.7 + *
    79.8 + * This program is free software: you can redistribute it and/or modify
    79.9 + * it under the terms of the GNU General Public License as published by
   79.10 + * the Free Software Foundation, version 2 of the License.
   79.11 + *
   79.12 + * This program is distributed in the hope that it will be useful,
   79.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   79.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   79.15 + * GNU General Public License for more details.
   79.16 + *
   79.17 + * You should have received a copy of the GNU General Public License
   79.18 + * along with this program. Look for COPYING file in the top folder.
   79.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   79.20 + */
   79.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   79.22 +
   79.23 +import java.lang.reflect.Method;
   79.24 +import java.util.List;
   79.25 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
   79.26 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   79.27 +
   79.28 +/** Provides binding between models and bck2brwsr VM.
   79.29 + *
   79.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   79.31 + */
   79.32 +@ExtraJavaScript(resource = "/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js")
   79.33 +final class Knockout {
   79.34 +    /** used by tests */
   79.35 +    static Knockout next;
   79.36 +    private final Object model;
   79.37 +
   79.38 +    Knockout(Object model) {
   79.39 +        this.model = model == null ? this : model;
   79.40 +    }
   79.41 +    
   79.42 +    public static <M> Knockout applyBindings(
   79.43 +        Object model, String[] propsGettersAndSetters,
   79.44 +        String[] methodsAndSignatures
   79.45 +    ) {
   79.46 +        applyImpl(propsGettersAndSetters, model.getClass(), model, model, methodsAndSignatures);
   79.47 +        return new Knockout(model);
   79.48 +    }
   79.49 +    public static <M> Knockout applyBindings(
   79.50 +        Class<M> modelClass, M model, String[] propsGettersAndSetters,
   79.51 +        String[] methodsAndSignatures
   79.52 +    ) {
   79.53 +        Knockout bindings = next;
   79.54 +        next = null;
   79.55 +        if (bindings == null) {
   79.56 +            bindings = new Knockout(null);
   79.57 +        }
   79.58 +        applyImpl(propsGettersAndSetters, modelClass, bindings, model, methodsAndSignatures);
   79.59 +        applyBindings(bindings);
   79.60 +        return bindings;
   79.61 +    }
   79.62 +
   79.63 +    public void valueHasMutated(String prop) {
   79.64 +        valueHasMutated(model, prop);
   79.65 +    }
   79.66 +    @JavaScriptBody(args = { "self", "prop" }, body =
   79.67 +        "var p = self[prop]; if (p) p.valueHasMutated();"
   79.68 +    )
   79.69 +    public static void valueHasMutated(Object self, String prop) {
   79.70 +    }
   79.71 +    
   79.72 +
   79.73 +    @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));")
   79.74 +    public static void triggerEvent(String id, String ev) {
   79.75 +    }
   79.76 +    
   79.77 +    @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive", "array" }, body =
   79.78 +          "var bnd = {\n"
   79.79 +        + "  'read': function() {\n"
   79.80 +        + "    var v = model[getter]();\n"
   79.81 +        + "    if (array) v = v.koArray(); else if (v !== null) v = v.valueOf();\n"
   79.82 +        + "    return v;\n"
   79.83 +        + "  },\n"
   79.84 +        + "  'owner': bindings\n"
   79.85 +        + "};\n"
   79.86 +        + "if (setter != null) {\n"
   79.87 +        + "  bnd['write'] = function(val) {\n"
   79.88 +        + "    var v = val === null ? null : val.valueOf();"
   79.89 +        + "    model[setter](v);\n"
   79.90 +        + "  };\n"
   79.91 +        + "}\n"
   79.92 +        + "bindings[prop] = ko['computed'](bnd);"
   79.93 +    )
   79.94 +    static void bind(
   79.95 +        Object bindings, Object model, String prop, String getter, String setter, boolean primitive, boolean array
   79.96 +    ) {
   79.97 +    }
   79.98 +
   79.99 +    @JavaScriptBody(args = { "bindings", "model", "prop", "sig" }, body = 
  79.100 +        "bindings[prop] = function(data, ev) { model[sig](data, ev); };"
  79.101 +    )
  79.102 +    static void expose(
  79.103 +        Object bindings, Object model, String prop, String sig
  79.104 +    ) {
  79.105 +    }
  79.106 +    
  79.107 +    @JavaScriptBody(args = { "bindings" }, body = "ko.applyBindings(bindings);")
  79.108 +    static void applyBindings(Object bindings) {}
  79.109 +    
  79.110 +    private static void applyImpl(
  79.111 +        String[] propsGettersAndSetters,
  79.112 +        Class<?> modelClass,
  79.113 +        Object bindings,
  79.114 +        Object model,
  79.115 +        String[] methodsAndSignatures
  79.116 +    ) throws IllegalStateException, SecurityException {
  79.117 +        for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
  79.118 +            try {
  79.119 +                Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
  79.120 +                bind(bindings, model, propsGettersAndSetters[i],
  79.121 +                    propsGettersAndSetters[i + 1],
  79.122 +                    propsGettersAndSetters[i + 2],
  79.123 +                    getter.getReturnType().isPrimitive(),
  79.124 +                    List.class.isAssignableFrom(getter.getReturnType()));
  79.125 +            } catch (NoSuchMethodException ex) {
  79.126 +                throw new IllegalStateException(ex.getMessage());
  79.127 +            }
  79.128 +        }
  79.129 +        for (int i = 0; i < methodsAndSignatures.length; i += 2) {
  79.130 +            expose(
  79.131 +                bindings, model, methodsAndSignatures[i], methodsAndSignatures[i + 1]);
  79.132 +        }
  79.133 +    }
  79.134 +}
    80.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    80.2 +++ b/ko/bck2brwsr/src/main/java/org/apidesign/bck2brwsr/ko2brwsr/LoadWS.java	Mon Oct 07 14:20:58 2013 +0200
    80.3 @@ -0,0 +1,126 @@
    80.4 +/**
    80.5 + * Back 2 Browser Bytecode Translator
    80.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    80.7 + *
    80.8 + * This program is free software: you can redistribute it and/or modify
    80.9 + * it under the terms of the GNU General Public License as published by
   80.10 + * the Free Software Foundation, version 2 of the License.
   80.11 + *
   80.12 + * This program is distributed in the hope that it will be useful,
   80.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   80.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   80.15 + * GNU General Public License for more details.
   80.16 + *
   80.17 + * You should have received a copy of the GNU General Public License
   80.18 + * along with this program. Look for COPYING file in the top folder.
   80.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   80.20 + */
   80.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   80.22 +
   80.23 +import net.java.html.js.JavaScriptBody;
   80.24 +import org.apidesign.html.json.spi.JSONCall;
   80.25 +
   80.26 +/** Communication with WebSockets for WebView 1.8.
   80.27 + *
   80.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   80.29 + */
   80.30 +final class LoadWS {
   80.31 +    private static final boolean SUPPORTED = isWebSocket();
   80.32 +    private final Object ws;
   80.33 +    private final JSONCall call;
   80.34 +    LoadWS(JSONCall first, String url) {
   80.35 +        call = first;
   80.36 +        ws = initWebSocket(this, url);
   80.37 +        if (ws == null) {
   80.38 +            first.notifyError(new IllegalArgumentException("Wrong URL: " + url));
   80.39 +        }
   80.40 +    }
   80.41 +    
   80.42 +    static boolean isSupported() {
   80.43 +        return SUPPORTED;
   80.44 +    }
   80.45 +    
   80.46 +    void send(JSONCall call) {
   80.47 +        push(call);
   80.48 +    }
   80.49 +    
   80.50 +    private synchronized void push(JSONCall call) {
   80.51 +        send(ws, call.getMessage());
   80.52 +    }
   80.53 +
   80.54 +    void onOpen(Object ev) {
   80.55 +        if (!call.isDoOutput()) {
   80.56 +            call.notifySuccess(null);
   80.57 +        }
   80.58 +    }
   80.59 +    
   80.60 +    
   80.61 +    @JavaScriptBody(args = { "data" }, body = "try {\n"
   80.62 +        + "    return eval('(' + data + ')');\n"
   80.63 +        + "  } catch (error) {;\n"
   80.64 +        + "    return data;\n"
   80.65 +        + "  }\n"
   80.66 +    )
   80.67 +    private static native Object toJSON(String data);
   80.68 +    
   80.69 +    void onMessage(Object ev, String data) {
   80.70 +        Object json = toJSON(data);
   80.71 +        call.notifySuccess(json);
   80.72 +    }
   80.73 +    
   80.74 +    void onError(Object ev) {
   80.75 +        call.notifyError(new Exception(ev.toString()));
   80.76 +    }
   80.77 +
   80.78 +    void onClose(boolean wasClean, int code, String reason) {
   80.79 +        call.notifyError(null);
   80.80 +    }
   80.81 +    
   80.82 +    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
   80.83 +    private static boolean isWebSocket() {
   80.84 +        return false;
   80.85 +    }
   80.86 +
   80.87 +    @JavaScriptBody(args = { "back", "url" }, javacall = true, body = ""
   80.88 +        + "if (window.WebSocket) {\n"
   80.89 +        + "  try {\n"
   80.90 +        + "    var ws = new window.WebSocket(url);\n"
   80.91 +        + "    ws.onopen = function(ev) {\n"
   80.92 +        + "      back.@org.apidesign.bck2brwsr.ko2brwsr.LoadWS::onOpen(Ljava/lang/Object;)(ev);\n"
   80.93 +        + "    };\n"
   80.94 +        + "    ws.onmessage = function(ev) {\n"
   80.95 +        + "      back.@org.apidesign.bck2brwsr.ko2brwsr.LoadWS::onMessage(Ljava/lang/Object;Ljava/lang/String;)(ev, ev.data);\n"
   80.96 +        + "    };\n"
   80.97 +        + "    ws.onerror = function(ev) {\n"
   80.98 +        + "      back.@org.apidesign.bck2brwsr.ko2brwsr.LoadWS::onError(Ljava/lang/Object;)(ev);\n"
   80.99 +        + "    };\n"
  80.100 +        + "    ws.onclose = function(ev) {\n"
  80.101 +        + "      back.@org.apidesign.bck2brwsr.ko2brwsr.LoadWS::onClose(ZILjava/lang/String;)(ev.wasClean, ev.code, ev.reason);\n"
  80.102 +        + "    };\n"
  80.103 +        + "    return ws;\n"
  80.104 +        + "  } catch (ex) {\n"
  80.105 +        + "    return null;\n"
  80.106 +        + "  }\n"
  80.107 +        + "} else {\n"
  80.108 +        + "  return null;\n"
  80.109 +        + "}\n"
  80.110 +    )
  80.111 +    private static Object initWebSocket(Object back, String url) {
  80.112 +        return null;
  80.113 +    }
  80.114 +    
  80.115 +
  80.116 +    @JavaScriptBody(args = { "ws", "msg" }, body = ""
  80.117 +        + "ws.send(msg);"
  80.118 +    )
  80.119 +    private void send(Object ws, String msg) {
  80.120 +    }
  80.121 +
  80.122 +    @JavaScriptBody(args = { "ws" }, body = "ws.close();")
  80.123 +    private static void close(Object ws) {
  80.124 +    }
  80.125 +
  80.126 +    void close() {
  80.127 +        close(ws);
  80.128 +    }
  80.129 +}
    81.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    81.2 +++ b/ko/bck2brwsr/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout-2.2.1.js	Mon Oct 07 14:20:58 2013 +0200
    81.3 @@ -0,0 +1,3614 @@
    81.4 +/*
    81.5 + * HTML via Java(tm) Language Bindings
    81.6 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    81.7 + *
    81.8 + * This program is free software: you can redistribute it and/or modify
    81.9 + * it under the terms of the GNU General Public License as published by
   81.10 + * the Free Software Foundation, version 2 of the License.
   81.11 + *
   81.12 + * This program is distributed in the hope that it will be useful,
   81.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   81.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   81.15 + * GNU General Public License for more details. apidesign.org
   81.16 + * designates this particular file as subject to the
   81.17 + * "Classpath" exception as provided by apidesign.org
   81.18 + * in the License file that accompanied this code.
   81.19 + *
   81.20 + * You should have received a copy of the GNU General Public License
   81.21 + * along with this program. Look for COPYING file in the top folder.
   81.22 + * If not, see http://wiki.apidesign.org/wiki/GPLwithClassPathException
   81.23 + */
   81.24 +// Knockout JavaScript library v2.2.1
   81.25 +// (c) Steven Sanderson - http://knockoutjs.com/
   81.26 +// License: MIT (http://www.opensource.org/licenses/mit-license.php)
   81.27 +
   81.28 +(function(){
   81.29 +var DEBUG=true;
   81.30 +(function(window,document,navigator,jQuery,undefined){
   81.31 +!function(factory) {
   81.32 +    // Support three module loading scenarios
   81.33 +    if (typeof require === 'function' && typeof exports === 'object' && typeof module === 'object') {
   81.34 +        // [1] CommonJS/Node.js
   81.35 +        var target = module['exports'] || exports; // module.exports is for Node.js
   81.36 +        factory(target);
   81.37 +    } else if (typeof define === 'function' && define['amd']) {
   81.38 +        // [2] AMD anonymous module
   81.39 +        define(['exports'], factory);
   81.40 +    } else {
   81.41 +        // [3] No module loader (plain <script> tag) - put directly in global namespace
   81.42 +        factory(window['ko'] = {});
   81.43 +    }
   81.44 +}(function(koExports){
   81.45 +// Internally, all KO objects are attached to koExports (even the non-exported ones whose names will be minified by the closure compiler).
   81.46 +// In the future, the following "ko" variable may be made distinct from "koExports" so that private objects are not externally reachable.
   81.47 +var ko = typeof koExports !== 'undefined' ? koExports : {};
   81.48 +// Google Closure Compiler helpers (used only to make the minified file smaller)
   81.49 +ko.exportSymbol = function(koPath, object) {
   81.50 +	var tokens = koPath.split(".");
   81.51 +
   81.52 +	// In the future, "ko" may become distinct from "koExports" (so that non-exported objects are not reachable)
   81.53 +	// At that point, "target" would be set to: (typeof koExports !== "undefined" ? koExports : ko)
   81.54 +	var target = ko;
   81.55 +
   81.56 +	for (var i = 0; i < tokens.length - 1; i++)
   81.57 +		target = target[tokens[i]];
   81.58 +	target[tokens[tokens.length - 1]] = object;
   81.59 +};
   81.60 +ko.exportProperty = function(owner, publicName, object) {
   81.61 +  owner[publicName] = object;
   81.62 +};
   81.63 +ko.version = "2.2.1";
   81.64 +
   81.65 +ko.exportSymbol('version', ko.version);
   81.66 +ko.utils = new (function () {
   81.67 +    var stringTrimRegex = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;
   81.68 +
   81.69 +    // Represent the known event types in a compact way, then at runtime transform it into a hash with event name as key (for fast lookup)
   81.70 +    var knownEvents = {}, knownEventTypesByEventName = {};
   81.71 +    var keyEventTypeName = /Firefox\/2/i.test(navigator.userAgent) ? 'KeyboardEvent' : 'UIEvents';
   81.72 +    knownEvents[keyEventTypeName] = ['keyup', 'keydown', 'keypress'];
   81.73 +    knownEvents['MouseEvents'] = ['click', 'dblclick', 'mousedown', 'mouseup', 'mousemove', 'mouseover', 'mouseout', 'mouseenter', 'mouseleave'];
   81.74 +    for (var eventType in knownEvents) {
   81.75 +        var knownEventsForType = knownEvents[eventType];
   81.76 +        if (knownEventsForType.length) {
   81.77 +            for (var i = 0, j = knownEventsForType.length; i < j; i++)
   81.78 +                knownEventTypesByEventName[knownEventsForType[i]] = eventType;
   81.79 +        }
   81.80 +    }
   81.81 +    var eventsThatMustBeRegisteredUsingAttachEvent = { 'propertychange': true }; // Workaround for an IE9 issue - https://github.com/SteveSanderson/knockout/issues/406
   81.82 +
   81.83 +    // Detect IE versions for bug workarounds (uses IE conditionals, not UA string, for robustness)
   81.84 +    // Note that, since IE 10 does not support conditional comments, the following logic only detects IE < 10.
   81.85 +    // Currently this is by design, since IE 10+ behaves correctly when treated as a standard browser.
   81.86 +    // If there is a future need to detect specific versions of IE10+, we will amend this.
   81.87 +    var ieVersion = (function() {
   81.88 +        var version = 3, div = document.createElement('div'), iElems = div.getElementsByTagName('i');
   81.89 +
   81.90 +        // Keep constructing conditional HTML blocks until we hit one that resolves to an empty fragment
   81.91 +        while (
   81.92 +            div.innerHTML = '<!--[if gt IE ' + (++version) + ']><i></i><![endif]-->',
   81.93 +            iElems[0]
   81.94 +        );
   81.95 +        return version > 4 ? version : undefined;
   81.96 +    }());
   81.97 +    var isIe6 = ieVersion === 6,
   81.98 +        isIe7 = ieVersion === 7;
   81.99 +
  81.100 +    function isClickOnCheckableElement(element, eventType) {
  81.101 +        if ((ko.utils.tagNameLower(element) !== "input") || !element.type) return false;
  81.102 +        if (eventType.toLowerCase() != "click") return false;
  81.103 +        var inputType = element.type;
  81.104 +        return (inputType == "checkbox") || (inputType == "radio");
  81.105 +    }
  81.106 +
  81.107 +    return {
  81.108 +        fieldsIncludedWithJsonPost: ['authenticity_token', /^__RequestVerificationToken(_.*)?$/],
  81.109 +
  81.110 +        arrayForEach: function (array, action) {
  81.111 +            for (var i = 0, j = array.length; i < j; i++)
  81.112 +                action(array[i]);
  81.113 +        },
  81.114 +
  81.115 +        arrayIndexOf: function (array, item) {
  81.116 +            if (typeof Array.prototype.indexOf == "function")
  81.117 +                return Array.prototype.indexOf.call(array, item);
  81.118 +            for (var i = 0, j = array.length; i < j; i++)
  81.119 +                if (array[i] === item)
  81.120 +                    return i;
  81.121 +            return -1;
  81.122 +        },
  81.123 +
  81.124 +        arrayFirst: function (array, predicate, predicateOwner) {
  81.125 +            for (var i = 0, j = array.length; i < j; i++)
  81.126 +                if (predicate.call(predicateOwner, array[i]))
  81.127 +                    return array[i];
  81.128 +            return null;
  81.129 +        },
  81.130 +
  81.131 +        arrayRemoveItem: function (array, itemToRemove) {
  81.132 +            var index = ko.utils.arrayIndexOf(array, itemToRemove);
  81.133 +            if (index >= 0)
  81.134 +                array.splice(index, 1);
  81.135 +        },
  81.136 +
  81.137 +        arrayGetDistinctValues: function (array) {
  81.138 +            array = array || [];
  81.139 +            var result = [];
  81.140 +            for (var i = 0, j = array.length; i < j; i++) {
  81.141 +                if (ko.utils.arrayIndexOf(result, array[i]) < 0)
  81.142 +                    result.push(array[i]);
  81.143 +            }
  81.144 +            return result;
  81.145 +        },
  81.146 +
  81.147 +        arrayMap: function (array, mapping) {
  81.148 +            array = array || [];
  81.149 +            var result = [];
  81.150 +            for (var i = 0, j = array.length; i < j; i++)
  81.151 +                result.push(mapping(array[i]));
  81.152 +            return result;
  81.153 +        },
  81.154 +
  81.155 +        arrayFilter: function (array, predicate) {
  81.156 +            array = array || [];
  81.157 +            var result = [];
  81.158 +            for (var i = 0, j = array.length; i < j; i++)
  81.159 +                if (predicate(array[i]))
  81.160 +                    result.push(array[i]);
  81.161 +            return result;
  81.162 +        },
  81.163 +
  81.164 +        arrayPushAll: function (array, valuesToPush) {
  81.165 +            if (valuesToPush instanceof Array)
  81.166 +                array.push.apply(array, valuesToPush);
  81.167 +            else
  81.168 +                for (var i = 0, j = valuesToPush.length; i < j; i++)
  81.169 +                    array.push(valuesToPush[i]);
  81.170 +            return array;
  81.171 +        },
  81.172 +
  81.173 +        extend: function (target, source) {
  81.174 +            if (source) {
  81.175 +                for(var prop in source) {
  81.176 +                    if(source.hasOwnProperty(prop)) {
  81.177 +                        target[prop] = source[prop];
  81.178 +                    }
  81.179 +                }
  81.180 +            }
  81.181 +            return target;
  81.182 +        },
  81.183 +
  81.184 +        emptyDomNode: function (domNode) {
  81.185 +            while (domNode.firstChild) {
  81.186 +                ko.removeNode(domNode.firstChild);
  81.187 +            }
  81.188 +        },
  81.189 +
  81.190 +        moveCleanedNodesToContainerElement: function(nodes) {
  81.191 +            // Ensure it's a real array, as we're about to reparent the nodes and
  81.192 +            // we don't want the underlying collection to change while we're doing that.
  81.193 +            var nodesArray = ko.utils.makeArray(nodes);
  81.194 +
  81.195 +            var container = document.createElement('div');
  81.196 +            for (var i = 0, j = nodesArray.length; i < j; i++) {
  81.197 +                container.appendChild(ko.cleanNode(nodesArray[i]));
  81.198 +            }
  81.199 +            return container;
  81.200 +        },
  81.201 +
  81.202 +        cloneNodes: function (nodesArray, shouldCleanNodes) {
  81.203 +            for (var i = 0, j = nodesArray.length, newNodesArray = []; i < j; i++) {
  81.204 +                var clonedNode = nodesArray[i].cloneNode(true);
  81.205 +                newNodesArray.push(shouldCleanNodes ? ko.cleanNode(clonedNode) : clonedNode);
  81.206 +            }
  81.207 +            return newNodesArray;
  81.208 +        },
  81.209 +
  81.210 +        setDomNodeChildren: function (domNode, childNodes) {
  81.211 +            ko.utils.emptyDomNode(domNode);
  81.212 +            if (childNodes) {
  81.213 +                for (var i = 0, j = childNodes.length; i < j; i++)
  81.214 +                    domNode.appendChild(childNodes[i]);
  81.215 +            }
  81.216 +        },
  81.217 +
  81.218 +        replaceDomNodes: function (nodeToReplaceOrNodeArray, newNodesArray) {
  81.219 +            var nodesToReplaceArray = nodeToReplaceOrNodeArray.nodeType ? [nodeToReplaceOrNodeArray] : nodeToReplaceOrNodeArray;
  81.220 +            if (nodesToReplaceArray.length > 0) {
  81.221 +                var insertionPoint = nodesToReplaceArray[0];
  81.222 +                var parent = insertionPoint.parentNode;
  81.223 +                for (var i = 0, j = newNodesArray.length; i < j; i++)
  81.224 +                    parent.insertBefore(newNodesArray[i], insertionPoint);
  81.225 +                for (var i = 0, j = nodesToReplaceArray.length; i < j; i++) {
  81.226 +                    ko.removeNode(nodesToReplaceArray[i]);
  81.227 +                }
  81.228 +            }
  81.229 +        },
  81.230 +
  81.231 +        setOptionNodeSelectionState: function (optionNode, isSelected) {
  81.232 +            // IE6 sometimes throws "unknown error" if you try to write to .selected directly, whereas Firefox struggles with setAttribute. Pick one based on browser.
  81.233 +            if (ieVersion < 7)
  81.234 +                optionNode.setAttribute("selected", isSelected);
  81.235 +            else
  81.236 +                optionNode.selected = isSelected;
  81.237 +        },
  81.238 +
  81.239 +        stringTrim: function (string) {
  81.240 +            return (string || "").replace(stringTrimRegex, "");
  81.241 +        },
  81.242 +
  81.243 +        stringTokenize: function (string, delimiter) {
  81.244 +            var result = [];
  81.245 +            var tokens = (string || "").split(delimiter);
  81.246 +            for (var i = 0, j = tokens.length; i < j; i++) {
  81.247 +                var trimmed = ko.utils.stringTrim(tokens[i]);
  81.248 +                if (trimmed !== "")
  81.249 +                    result.push(trimmed);
  81.250 +            }
  81.251 +            return result;
  81.252 +        },
  81.253 +
  81.254 +        stringStartsWith: function (string, startsWith) {
  81.255 +            string = string || "";
  81.256 +            if (startsWith.length > string.length)
  81.257 +                return false;
  81.258 +            return string.substring(0, startsWith.length) === startsWith;
  81.259 +        },
  81.260 +
  81.261 +        domNodeIsContainedBy: function (node, containedByNode) {
  81.262 +            if (containedByNode.compareDocumentPosition)
  81.263 +                return (containedByNode.compareDocumentPosition(node) & 16) == 16;
  81.264 +            while (node != null) {
  81.265 +                if (node == containedByNode)
  81.266 +                    return true;
  81.267 +                node = node.parentNode;
  81.268 +            }
  81.269 +            return false;
  81.270 +        },
  81.271 +
  81.272 +        domNodeIsAttachedToDocument: function (node) {
  81.273 +            return ko.utils.domNodeIsContainedBy(node, node.ownerDocument);
  81.274 +        },
  81.275 +
  81.276 +        tagNameLower: function(element) {
  81.277 +            // For HTML elements, tagName will always be upper case; for XHTML elements, it'll be lower case.
  81.278 +            // Possible future optimization: If we know it's an element from an XHTML document (not HTML),
  81.279 +            // we don't need to do the .toLowerCase() as it will always be lower case anyway.
  81.280 +            return element && element.tagName && element.tagName.toLowerCase();
  81.281 +        },
  81.282 +
  81.283 +        registerEventHandler: function (element, eventType, handler) {
  81.284 +            var mustUseAttachEvent = ieVersion && eventsThatMustBeRegisteredUsingAttachEvent[eventType];
  81.285 +            if (!mustUseAttachEvent && typeof jQuery != "undefined") {
  81.286 +                if (isClickOnCheckableElement(element, eventType)) {
  81.287 +                    // For click events on checkboxes, jQuery interferes with the event handling in an awkward way:
  81.288 +                    // it toggles the element checked state *after* the click event handlers run, whereas native
  81.289 +                    // click events toggle the checked state *before* the event handler.
  81.290 +                    // Fix this by intecepting the handler and applying the correct checkedness before it runs.
  81.291 +                    var originalHandler = handler;
  81.292 +                    handler = function(event, eventData) {
  81.293 +                        var jQuerySuppliedCheckedState = this.checked;
  81.294 +                        if (eventData)
  81.295 +                            this.checked = eventData.checkedStateBeforeEvent !== true;
  81.296 +                        originalHandler.call(this, event);
  81.297 +                        this.checked = jQuerySuppliedCheckedState; // Restore the state jQuery applied
  81.298 +                    };
  81.299 +                }
  81.300 +                jQuery(element)['bind'](eventType, handler);
  81.301 +            } else if (!mustUseAttachEvent && typeof element.addEventListener == "function")
  81.302 +                element.addEventListener(eventType, handler, false);
  81.303 +            else if (typeof element.attachEvent != "undefined")
  81.304 +                element.attachEvent("on" + eventType, function (event) {
  81.305 +                    handler.call(element, event);
  81.306 +                });
  81.307 +            else
  81.308 +                throw new Error("Browser doesn't support addEventListener or attachEvent");
  81.309 +        },
  81.310 +
  81.311 +        triggerEvent: function (element, eventType) {
  81.312 +            if (!(element && element.nodeType))
  81.313 +                throw new Error("element must be a DOM node when calling triggerEvent");
  81.314 +
  81.315 +            if (typeof jQuery != "undefined") {
  81.316 +                var eventData = [];
  81.317 +                if (isClickOnCheckableElement(element, eventType)) {
  81.318 +                    // Work around the jQuery "click events on checkboxes" issue described above by storing the original checked state before triggering the handler
  81.319 +                    eventData.push({ checkedStateBeforeEvent: element.checked });
  81.320 +                }
  81.321 +                jQuery(element)['trigger'](eventType, eventData);
  81.322 +            } else if (typeof document.createEvent == "function") {
  81.323 +                if (typeof element.dispatchEvent == "function") {
  81.324 +                    var eventCategory = knownEventTypesByEventName[eventType] || "HTMLEvents";
  81.325 +                    var event = document.createEvent(eventCategory);
  81.326 +                    event.initEvent(eventType, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, element);
  81.327 +                    element.dispatchEvent(event);
  81.328 +                }
  81.329 +                else
  81.330 +                    throw new Error("The supplied element doesn't support dispatchEvent");
  81.331 +            } else if (typeof element.fireEvent != "undefined") {
  81.332 +                // Unlike other browsers, IE doesn't change the checked state of checkboxes/radiobuttons when you trigger their "click" event
  81.333 +                // so to make it consistent, we'll do it manually here
  81.334 +                if (isClickOnCheckableElement(element, eventType))
  81.335 +                    element.checked = element.checked !== true;
  81.336 +                element.fireEvent("on" + eventType);
  81.337 +            }
  81.338 +            else
  81.339 +                throw new Error("Browser doesn't support triggering events");
  81.340 +        },
  81.341 +
  81.342 +        unwrapObservable: function (value) {
  81.343 +            return ko.isObservable(value) ? value() : value;
  81.344 +        },
  81.345 +
  81.346 +        peekObservable: function (value) {
  81.347 +            return ko.isObservable(value) ? value.peek() : value;
  81.348 +        },
  81.349 +
  81.350 +        toggleDomNodeCssClass: function (node, classNames, shouldHaveClass) {
  81.351 +            if (classNames) {
  81.352 +                var cssClassNameRegex = /[\w-]+/g,
  81.353 +                    currentClassNames = node.className.match(cssClassNameRegex) || [];
  81.354 +                ko.utils.arrayForEach(classNames.match(cssClassNameRegex), function(className) {
  81.355 +                    var indexOfClass = ko.utils.arrayIndexOf(currentClassNames, className);
  81.356 +                    if (indexOfClass >= 0) {
  81.357 +                        if (!shouldHaveClass)
  81.358 +                            currentClassNames.splice(indexOfClass, 1);
  81.359 +                    } else {
  81.360 +                        if (shouldHaveClass)
  81.361 +                            currentClassNames.push(className);
  81.362 +                    }
  81.363 +                });
  81.364 +                node.className = currentClassNames.join(" ");
  81.365 +            }
  81.366 +        },
  81.367 +
  81.368 +        setTextContent: function(element, textContent) {
  81.369 +            var value = ko.utils.unwrapObservable(textContent);
  81.370 +            if ((value === null) || (value === undefined))
  81.371 +                value = "";
  81.372 +
  81.373 +            if (element.nodeType === 3) {
  81.374 +                element.data = value;
  81.375 +            } else {
  81.376 +                // We need there to be exactly one child: a text node.
  81.377 +                // If there are no children, more than one, or if it's not a text node,
  81.378 +                // we'll clear everything and create a single text node.
  81.379 +                var innerTextNode = ko.virtualElements.firstChild(element);
  81.380 +                if (!innerTextNode || innerTextNode.nodeType != 3 || ko.virtualElements.nextSibling(innerTextNode)) {
  81.381 +                    ko.virtualElements.setDomNodeChildren(element, [document.createTextNode(value)]);
  81.382 +                } else {
  81.383 +                    innerTextNode.data = value;
  81.384 +                }
  81.385 +
  81.386 +                ko.utils.forceRefresh(element);
  81.387 +            }
  81.388 +        },
  81.389 +
  81.390 +        setElementName: function(element, name) {
  81.391 +            element.name = name;
  81.392 +
  81.393 +            // Workaround IE 6/7 issue
  81.394 +            // - https://github.com/SteveSanderson/knockout/issues/197
  81.395 +            // - http://www.matts411.com/post/setting_the_name_attribute_in_ie_dom/
  81.396 +            if (ieVersion <= 7) {
  81.397 +                try {
  81.398 +                    element.mergeAttributes(document.createElement("<input name='" + element.name + "'/>"), false);
  81.399 +                }
  81.400 +                catch(e) {} // For IE9 with doc mode "IE9 Standards" and browser mode "IE9 Compatibility View"
  81.401 +            }
  81.402 +        },
  81.403 +
  81.404 +        forceRefresh: function(node) {
  81.405 +            // Workaround for an IE9 rendering bug - https://github.com/SteveSanderson/knockout/issues/209
  81.406 +            if (ieVersion >= 9) {
  81.407 +                // For text nodes and comment nodes (most likely virtual elements), we will have to refresh the container
  81.408 +                var elem = node.nodeType == 1 ? node : node.parentNode;
  81.409 +                if (elem.style)
  81.410 +                    elem.style.zoom = elem.style.zoom;
  81.411 +            }
  81.412 +        },
  81.413 +
  81.414 +        ensureSelectElementIsRenderedCorrectly: function(selectElement) {
  81.415 +            // Workaround for IE9 rendering bug - it doesn't reliably display all the text in dynamically-added select boxes unless you force it to re-render by updating the width.
  81.416 +            // (See https://github.com/SteveSanderson/knockout/issues/312, http://stackoverflow.com/questions/5908494/select-only-shows-first-char-of-selected-option)
  81.417 +            if (ieVersion >= 9) {
  81.418 +                var originalWidth = selectElement.style.width;
  81.419 +                selectElement.style.width = 0;
  81.420 +                selectElement.style.width = originalWidth;
  81.421 +            }
  81.422 +        },
  81.423 +
  81.424 +        range: function (min, max) {
  81.425 +            min = ko.utils.unwrapObservable(min);
  81.426 +            max = ko.utils.unwrapObservable(max);
  81.427 +            var result = [];
  81.428 +            for (var i = min; i <= max; i++)
  81.429 +                result.push(i);
  81.430 +            return result;
  81.431 +        },
  81.432 +
  81.433 +        makeArray: function(arrayLikeObject) {
  81.434 +            var result = [];
  81.435 +            for (var i = 0, j = arrayLikeObject.length; i < j; i++) {
  81.436 +                result.push(arrayLikeObject[i]);
  81.437 +            };
  81.438 +            return result;
  81.439 +        },
  81.440 +
  81.441 +        isIe6 : isIe6,
  81.442 +        isIe7 : isIe7,
  81.443 +        ieVersion : ieVersion,
  81.444 +
  81.445 +        getFormFields: function(form, fieldName) {
  81.446 +            var fields = ko.utils.makeArray(form.getElementsByTagName("input")).concat(ko.utils.makeArray(form.getElementsByTagName("textarea")));
  81.447 +            var isMatchingField = (typeof fieldName == 'string')
  81.448 +                ? function(field) { return field.name === fieldName }
  81.449 +                : function(field) { return fieldName.test(field.name) }; // Treat fieldName as regex or object containing predicate
  81.450 +            var matches = [];
  81.451 +            for (var i = fields.length - 1; i >= 0; i--) {
  81.452 +                if (isMatchingField(fields[i]))
  81.453 +                    matches.push(fields[i]);
  81.454 +            };
  81.455 +            return matches;
  81.456 +        },
  81.457 +
  81.458 +        parseJson: function (jsonString) {
  81.459 +            if (typeof jsonString == "string") {
  81.460 +                jsonString = ko.utils.stringTrim(jsonString);
  81.461 +                if (jsonString) {
  81.462 +                    if (window.JSON && window.JSON.parse) // Use native parsing where available
  81.463 +                        return window.JSON.parse(jsonString);
  81.464 +                    return (new Function("return " + jsonString))(); // Fallback on less safe parsing for older browsers
  81.465 +                }
  81.466 +            }
  81.467 +            return null;
  81.468 +        },
  81.469 +
  81.470 +        stringifyJson: function (data, replacer, space) {   // replacer and space are optional
  81.471 +            if ((typeof JSON == "undefined") || (typeof JSON.stringify == "undefined"))
  81.472 +                throw new Error("Cannot find JSON.stringify(). Some browsers (e.g., IE < 8) don't support it natively, but you can overcome this by adding a script reference to json2.js, downloadable from http://www.json.org/json2.js");
  81.473 +            return JSON.stringify(ko.utils.unwrapObservable(data), replacer, space);
  81.474 +        },
  81.475 +
  81.476 +        postJson: function (urlOrForm, data, options) {
  81.477 +            options = options || {};
  81.478 +            var params = options['params'] || {};
  81.479 +            var includeFields = options['includeFields'] || this.fieldsIncludedWithJsonPost;
  81.480 +            var url = urlOrForm;
  81.481 +
  81.482 +            // If we were given a form, use its 'action' URL and pick out any requested field values
  81.483 +            if((typeof urlOrForm == 'object') && (ko.utils.tagNameLower(urlOrForm) === "form")) {
  81.484 +                var originalForm = urlOrForm;
  81.485 +                url = originalForm.action;
  81.486 +                for (var i = includeFields.length - 1; i >= 0; i--) {
  81.487 +                    var fields = ko.utils.getFormFields(originalForm, includeFields[i]);
  81.488 +                    for (var j = fields.length - 1; j >= 0; j--)
  81.489 +                        params[fields[j].name] = fields[j].value;
  81.490 +                }
  81.491 +            }
  81.492 +
  81.493 +            data = ko.utils.unwrapObservable(data);
  81.494 +            var form = document.createElement("form");
  81.495 +            form.style.display = "none";
  81.496 +            form.action = url;
  81.497 +            form.method = "post";
  81.498 +            for (var key in data) {
  81.499 +                var input = document.createElement("input");
  81.500 +                input.name = key;
  81.501 +                input.value = ko.utils.stringifyJson(ko.utils.unwrapObservable(data[key]));
  81.502 +                form.appendChild(input);
  81.503 +            }
  81.504 +            for (var key in params) {
  81.505 +                var input = document.createElement("input");
  81.506 +                input.name = key;
  81.507 +                input.value = params[key];
  81.508 +                form.appendChild(input);
  81.509 +            }
  81.510 +            document.body.appendChild(form);
  81.511 +            options['submitter'] ? options['submitter'](form) : form.submit();
  81.512 +            setTimeout(function () { form.parentNode.removeChild(form); }, 0);
  81.513 +        }
  81.514 +    }
  81.515 +})();
  81.516 +
  81.517 +ko.exportSymbol('utils', ko.utils);
  81.518 +ko.exportSymbol('utils.arrayForEach', ko.utils.arrayForEach);
  81.519 +ko.exportSymbol('utils.arrayFirst', ko.utils.arrayFirst);
  81.520 +ko.exportSymbol('utils.arrayFilter', ko.utils.arrayFilter);
  81.521 +ko.exportSymbol('utils.arrayGetDistinctValues', ko.utils.arrayGetDistinctValues);
  81.522 +ko.exportSymbol('utils.arrayIndexOf', ko.utils.arrayIndexOf);
  81.523 +ko.exportSymbol('utils.arrayMap', ko.utils.arrayMap);
  81.524 +ko.exportSymbol('utils.arrayPushAll', ko.utils.arrayPushAll);
  81.525 +ko.exportSymbol('utils.arrayRemoveItem', ko.utils.arrayRemoveItem);
  81.526 +ko.exportSymbol('utils.extend', ko.utils.extend);
  81.527 +ko.exportSymbol('utils.fieldsIncludedWithJsonPost', ko.utils.fieldsIncludedWithJsonPost);
  81.528 +ko.exportSymbol('utils.getFormFields', ko.utils.getFormFields);
  81.529 +ko.exportSymbol('utils.peekObservable', ko.utils.peekObservable);
  81.530 +ko.exportSymbol('utils.postJson', ko.utils.postJson);
  81.531 +ko.exportSymbol('utils.parseJson', ko.utils.parseJson);
  81.532 +ko.exportSymbol('utils.registerEventHandler', ko.utils.registerEventHandler);
  81.533 +ko.exportSymbol('utils.stringifyJson', ko.utils.stringifyJson);
  81.534 +ko.exportSymbol('utils.range', ko.utils.range);
  81.535 +ko.exportSymbol('utils.toggleDomNodeCssClass', ko.utils.toggleDomNodeCssClass);
  81.536 +ko.exportSymbol('utils.triggerEvent', ko.utils.triggerEvent);
  81.537 +ko.exportSymbol('utils.unwrapObservable', ko.utils.unwrapObservable);
  81.538 +
  81.539 +if (!Function.prototype['bind']) {
  81.540 +    // Function.prototype.bind is a standard part of ECMAScript 5th Edition (December 2009, http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-262.pdf)
  81.541 +    // In case the browser doesn't implement it natively, provide a JavaScript implementation. This implementation is based on the one in prototype.js
  81.542 +    Function.prototype['bind'] = function (object) {
  81.543 +        var originalFunction = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  81.544 +        return function () {
  81.545 +            return originalFunction.apply(object, args.concat(Array.prototype.slice.call(arguments)));
  81.546 +        };
  81.547 +    };
  81.548 +}
  81.549 +
  81.550 +ko.utils.domData = new (function () {
  81.551 +    var uniqueId = 0;
  81.552 +    var dataStoreKeyExpandoPropertyName = "__ko__" + (new Date).getTime();
  81.553 +    var dataStore = {};
  81.554 +    return {
  81.555 +        get: function (node, key) {
  81.556 +            var allDataForNode = ko.utils.domData.getAll(node, false);
  81.557 +            return allDataForNode === undefined ? undefined : allDataForNode[key];
  81.558 +        },
  81.559 +        set: function (node, key, value) {
  81.560 +            if (value === undefined) {
  81.561 +                // Make sure we don't actually create a new domData key if we are actually deleting a value
  81.562 +                if (ko.utils.domData.getAll(node, false) === undefined)
  81.563 +                    return;
  81.564 +            }
  81.565 +            var allDataForNode = ko.utils.domData.getAll(node, true);
  81.566 +            allDataForNode[key] = value;
  81.567 +        },
  81.568 +        getAll: function (node, createIfNotFound) {
  81.569 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
  81.570 +            var hasExistingDataStore = dataStoreKey && (dataStoreKey !== "null") && dataStore[dataStoreKey];
  81.571 +            if (!hasExistingDataStore) {
  81.572 +                if (!createIfNotFound)
  81.573 +                    return undefined;
  81.574 +                dataStoreKey = node[dataStoreKeyExpandoPropertyName] = "ko" + uniqueId++;
  81.575 +                dataStore[dataStoreKey] = {};
  81.576 +            }
  81.577 +            return dataStore[dataStoreKey];
  81.578 +        },
  81.579 +        clear: function (node) {
  81.580 +            var dataStoreKey = node[dataStoreKeyExpandoPropertyName];
  81.581 +            if (dataStoreKey) {
  81.582 +                delete dataStore[dataStoreKey];
  81.583 +                node[dataStoreKeyExpandoPropertyName] = null;
  81.584 +                return true; // Exposing "did clean" flag purely so specs can infer whether things have been cleaned up as intended
  81.585 +            }
  81.586 +            return false;
  81.587 +        }
  81.588 +    }
  81.589 +})();
  81.590 +
  81.591 +ko.exportSymbol('utils.domData', ko.utils.domData);
  81.592 +ko.exportSymbol('utils.domData.clear', ko.utils.domData.clear); // Exporting only so specs can clear up after themselves fully
  81.593 +
  81.594 +ko.utils.domNodeDisposal = new (function () {
  81.595 +    var domDataKey = "__ko_domNodeDisposal__" + (new Date).getTime();
  81.596 +    var cleanableNodeTypes = { 1: true, 8: true, 9: true };       // Element, Comment, Document
  81.597 +    var cleanableNodeTypesWithDescendants = { 1: true, 9: true }; // Element, Document
  81.598 +
  81.599 +    function getDisposeCallbacksCollection(node, createIfNotFound) {
  81.600 +        var allDisposeCallbacks = ko.utils.domData.get(node, domDataKey);
  81.601 +        if ((allDisposeCallbacks === undefined) && createIfNotFound) {
  81.602 +            allDisposeCallbacks = [];
  81.603 +            ko.utils.domData.set(node, domDataKey, allDisposeCallbacks);
  81.604 +        }
  81.605 +        return allDisposeCallbacks;
  81.606 +    }
  81.607 +    function destroyCallbacksCollection(node) {
  81.608 +        ko.utils.domData.set(node, domDataKey, undefined);
  81.609 +    }
  81.610 +
  81.611 +    function cleanSingleNode(node) {
  81.612 +        // Run all the dispose callbacks
  81.613 +        var callbacks = getDisposeCallbacksCollection(node, false);
  81.614 +        if (callbacks) {
  81.615 +            callbacks = callbacks.slice(0); // Clone, as the array may be modified during iteration (typically, callbacks will remove themselves)
  81.616 +            for (var i = 0; i < callbacks.length; i++)
  81.617 +                callbacks[i](node);
  81.618 +        }
  81.619 +
  81.620 +        // Also erase the DOM data
  81.621 +        ko.utils.domData.clear(node);
  81.622 +
  81.623 +        // Special support for jQuery here because it's so commonly used.
  81.624 +        // Many jQuery plugins (including jquery.tmpl) store data using jQuery's equivalent of domData
  81.625 +        // so notify it to tear down any resources associated with the node & descendants here.
  81.626 +        if ((typeof jQuery == "function") && (typeof jQuery['cleanData'] == "function"))
  81.627 +            jQuery['cleanData']([node]);
  81.628 +
  81.629 +        // Also clear any immediate-child comment nodes, as these wouldn't have been found by
  81.630 +        // node.getElementsByTagName("*") in cleanNode() (comment nodes aren't elements)
  81.631 +        if (cleanableNodeTypesWithDescendants[node.nodeType])
  81.632 +            cleanImmediateCommentTypeChildren(node);
  81.633 +    }
  81.634 +
  81.635 +    function cleanImmediateCommentTypeChildren(nodeWithChildren) {
  81.636 +        var child, nextChild = nodeWithChildren.firstChild;
  81.637 +        while (child = nextChild) {
  81.638 +            nextChild = child.nextSibling;
  81.639 +            if (child.nodeType === 8)
  81.640 +                cleanSingleNode(child);
  81.641 +        }
  81.642 +    }
  81.643 +
  81.644 +    return {
  81.645 +        addDisposeCallback : function(node, callback) {
  81.646 +            if (typeof callback != "function")
  81.647 +                throw new Error("Callback must be a function");
  81.648 +            getDisposeCallbacksCollection(node, true).push(callback);
  81.649 +        },
  81.650 +
  81.651 +        removeDisposeCallback : function(node, callback) {
  81.652 +            var callbacksCollection = getDisposeCallbacksCollection(node, false);
  81.653 +            if (callbacksCollection) {
  81.654 +                ko.utils.arrayRemoveItem(callbacksCollection, callback);
  81.655 +                if (callbacksCollection.length == 0)
  81.656 +                    destroyCallbacksCollection(node);
  81.657 +            }
  81.658 +        },
  81.659 +
  81.660 +        cleanNode : function(node) {
  81.661 +            // First clean this node, where applicable
  81.662 +            if (cleanableNodeTypes[node.nodeType]) {
  81.663 +                cleanSingleNode(node);
  81.664 +
  81.665 +                // ... then its descendants, where applicable
  81.666 +                if (cleanableNodeTypesWithDescendants[node.nodeType]) {
  81.667 +                    // Clone the descendants list in case it changes during iteration
  81.668 +                    var descendants = [];
  81.669 +                    ko.utils.arrayPushAll(descendants, node.getElementsByTagName("*"));
  81.670 +                    for (var i = 0, j = descendants.length; i < j; i++)
  81.671 +                        cleanSingleNode(descendants[i]);
  81.672 +                }
  81.673 +            }
  81.674 +            return node;
  81.675 +        },
  81.676 +
  81.677 +        removeNode : function(node) {
  81.678 +            ko.cleanNode(node);
  81.679 +            if (node.parentNode)
  81.680 +                node.parentNode.removeChild(node);
  81.681 +        }
  81.682 +    }
  81.683 +})();
  81.684 +ko.cleanNode = ko.utils.domNodeDisposal.cleanNode; // Shorthand name for convenience
  81.685 +ko.removeNode = ko.utils.domNodeDisposal.removeNode; // Shorthand name for convenience
  81.686 +ko.exportSymbol('cleanNode', ko.cleanNode);
  81.687 +ko.exportSymbol('removeNode', ko.removeNode);
  81.688 +ko.exportSymbol('utils.domNodeDisposal', ko.utils.domNodeDisposal);
  81.689 +ko.exportSymbol('utils.domNodeDisposal.addDisposeCallback', ko.utils.domNodeDisposal.addDisposeCallback);
  81.690 +ko.exportSymbol('utils.domNodeDisposal.removeDisposeCallback', ko.utils.domNodeDisposal.removeDisposeCallback);
  81.691 +(function () {
  81.692 +    var leadingCommentRegex = /^(\s*)<!--(.*?)-->/;
  81.693 +
  81.694 +    function simpleHtmlParse(html) {
  81.695 +        // Based on jQuery's "clean" function, but only accounting for table-related elements.
  81.696 +        // If you have referenced jQuery, this won't be used anyway - KO will use jQuery's "clean" function directly
  81.697 +
  81.698 +        // Note that there's still an issue in IE < 9 whereby it will discard comment nodes that are the first child of
  81.699 +        // a descendant node. For example: "<div><!-- mycomment -->abc</div>" will get parsed as "<div>abc</div>"
  81.700 +        // This won't affect anyone who has referenced jQuery, and there's always the workaround of inserting a dummy node
  81.701 +        // (possibly a text node) in front of the comment. So, KO does not attempt to workaround this IE issue automatically at present.
  81.702 +
  81.703 +        // Trim whitespace, otherwise indexOf won't work as expected
  81.704 +        var tags = ko.utils.stringTrim(html).toLowerCase(), div = document.createElement("div");
  81.705 +
  81.706 +        // Finds the first match from the left column, and returns the corresponding "wrap" data from the right column
  81.707 +        var wrap = tags.match(/^<(thead|tbody|tfoot)/)              && [1, "<table>", "</table>"] ||
  81.708 +                   !tags.indexOf("<tr")                             && [2, "<table><tbody>", "</tbody></table>"] ||
  81.709 +                   (!tags.indexOf("<td") || !tags.indexOf("<th"))   && [3, "<table><tbody><tr>", "</tr></tbody></table>"] ||
  81.710 +                   /* anything else */                                 [0, "", ""];
  81.711 +
  81.712 +        // Go to html and back, then peel off extra wrappers
  81.713 +        // Note that we always prefix with some dummy text, because otherwise, IE<9 will strip out leading comment nodes in descendants. Total madness.
  81.714 +        var markup = "ignored<div>" + wrap[1] + html + wrap[2] + "</div>";
  81.715 +        if (typeof window['innerShiv'] == "function") {
  81.716 +            div.appendChild(window['innerShiv'](markup));
  81.717 +        } else {
  81.718 +            div.innerHTML = markup;
  81.719 +        }
  81.720 +
  81.721 +        // Move to the right depth
  81.722 +        while (wrap[0]--)
  81.723 +            div = div.lastChild;
  81.724 +
  81.725 +        return ko.utils.makeArray(div.lastChild.childNodes);
  81.726 +    }
  81.727 +
  81.728 +    function jQueryHtmlParse(html) {
  81.729 +        // jQuery's "parseHTML" function was introduced in jQuery 1.8.0 and is a documented public API.
  81.730 +        if (jQuery['parseHTML']) {
  81.731 +            return jQuery['parseHTML'](html);
  81.732 +        } else {
  81.733 +            // For jQuery < 1.8.0, we fall back on the undocumented internal "clean" function.
  81.734 +            var elems = jQuery['clean']([html]);
  81.735 +
  81.736 +            // As of jQuery 1.7.1, jQuery parses the HTML by appending it to some dummy parent nodes held in an in-memory document fragment.
  81.737 +            // Unfortunately, it never clears the dummy parent nodes from the document fragment, so it leaks memory over time.
  81.738 +            // Fix this by finding the top-most dummy parent element, and detaching it from its owner fragment.
  81.739 +            if (elems && elems[0]) {
  81.740 +                // Find the top-most parent element that's a direct child of a document fragment
  81.741 +                var elem = elems[0];
  81.742 +                while (elem.parentNode && elem.parentNode.nodeType !== 11 /* i.e., DocumentFragment */)
  81.743 +                    elem = elem.parentNode;
  81.744 +                // ... then detach it
  81.745 +                if (elem.parentNode)
  81.746 +                    elem.parentNode.removeChild(elem);
  81.747 +            }
  81.748 +
  81.749 +            return elems;
  81.750 +        }
  81.751 +    }
  81.752 +
  81.753 +    ko.utils.parseHtmlFragment = function(html) {
  81.754 +        return typeof jQuery != 'undefined' ? jQueryHtmlParse(html)   // As below, benefit from jQuery's optimisations where possible
  81.755 +                                            : simpleHtmlParse(html);  // ... otherwise, this simple logic will do in most common cases.
  81.756 +    };
  81.757 +
  81.758 +    ko.utils.setHtml = function(node, html) {
  81.759 +        ko.utils.emptyDomNode(node);
  81.760 +
  81.761 +        // There's no legitimate reason to display a stringified observable without unwrapping it, so we'll unwrap it
  81.762 +        html = ko.utils.unwrapObservable(html);
  81.763 +
  81.764 +        if ((html !== null) && (html !== undefined)) {
  81.765 +            if (typeof html != 'string')
  81.766 +                html = html.toString();
  81.767 +
  81.768 +            // jQuery contains a lot of sophisticated code to parse arbitrary HTML fragments,
  81.769 +            // for example <tr> elements which are not normally allowed to exist on their own.
  81.770 +            // If you've referenced jQuery we'll use that rather than duplicating its code.
  81.771 +            if (typeof jQuery != 'undefined') {
  81.772 +                jQuery(node)['html'](html);
  81.773 +            } else {
  81.774 +                // ... otherwise, use KO's own parsing logic.
  81.775 +                var parsedNodes = ko.utils.parseHtmlFragment(html);
  81.776 +                for (var i = 0; i < parsedNodes.length; i++)
  81.777 +                    node.appendChild(parsedNodes[i]);
  81.778 +            }
  81.779 +        }
  81.780 +    };
  81.781 +})();
  81.782 +
  81.783 +ko.exportSymbol('utils.parseHtmlFragment', ko.utils.parseHtmlFragment);
  81.784 +ko.exportSymbol('utils.setHtml', ko.utils.setHtml);
  81.785 +
  81.786 +ko.memoization = (function () {
  81.787 +    var memos = {};
  81.788 +
  81.789 +    function randomMax8HexChars() {
  81.790 +        return (((1 + Math.random()) * 0x100000000) | 0).toString(16).substring(1);
  81.791 +    }
  81.792 +    function generateRandomId() {
  81.793 +        return randomMax8HexChars() + randomMax8HexChars();
  81.794 +    }
  81.795 +    function findMemoNodes(rootNode, appendToArray) {
  81.796 +        if (!rootNode)
  81.797 +            return;
  81.798 +        if (rootNode.nodeType == 8) {
  81.799 +            var memoId = ko.memoization.parseMemoText(rootNode.nodeValue);
  81.800 +            if (memoId != null)
  81.801 +                appendToArray.push({ domNode: rootNode, memoId: memoId });
  81.802 +        } else if (rootNode.nodeType == 1) {
  81.803 +            for (var i = 0, childNodes = rootNode.childNodes, j = childNodes.length; i < j; i++)
  81.804 +                findMemoNodes(childNodes[i], appendToArray);
  81.805 +        }
  81.806 +    }
  81.807 +
  81.808 +    return {
  81.809 +        memoize: function (callback) {
  81.810 +            if (typeof callback != "function")
  81.811 +                throw new Error("You can only pass a function to ko.memoization.memoize()");
  81.812 +            var memoId = generateRandomId();
  81.813 +            memos[memoId] = callback;
  81.814 +            return "<!--[ko_memo:" + memoId + "]-->";
  81.815 +        },
  81.816 +
  81.817 +        unmemoize: function (memoId, callbackParams) {
  81.818 +            var callback = memos[memoId];
  81.819 +            if (callback === undefined)
  81.820 +                throw new Error("Couldn't find any memo with ID " + memoId + ". Perhaps it's already been unmemoized.");
  81.821 +            try {
  81.822 +                callback.apply(null, callbackParams || []);
  81.823 +                return true;
  81.824 +            }
  81.825 +            finally { delete memos[memoId]; }
  81.826 +        },
  81.827 +
  81.828 +        unmemoizeDomNodeAndDescendants: function (domNode, extraCallbackParamsArray) {
  81.829 +            var memos = [];
  81.830 +            findMemoNodes(domNode, memos);
  81.831 +            for (var i = 0, j = memos.length; i < j; i++) {
  81.832 +                var node = memos[i].domNode;
  81.833 +                var combinedParams = [node];
  81.834 +                if (extraCallbackParamsArray)
  81.835 +                    ko.utils.arrayPushAll(combinedParams, extraCallbackParamsArray);
  81.836 +                ko.memoization.unmemoize(memos[i].memoId, combinedParams);
  81.837 +                node.nodeValue = ""; // Neuter this node so we don't try to unmemoize it again
  81.838 +                if (node.parentNode)
  81.839 +                    node.parentNode.removeChild(node); // If possible, erase it totally (not always possible - someone else might just hold a reference to it then call unmemoizeDomNodeAndDescendants again)
  81.840 +            }
  81.841 +        },
  81.842 +
  81.843 +        parseMemoText: function (memoText) {
  81.844 +            var match = memoText.match(/^\[ko_memo\:(.*?)\]$/);
  81.845 +            return match ? match[1] : null;
  81.846 +        }
  81.847 +    };
  81.848 +})();
  81.849 +
  81.850 +ko.exportSymbol('memoization', ko.memoization);
  81.851 +ko.exportSymbol('memoization.memoize', ko.memoization.memoize);
  81.852 +ko.exportSymbol('memoization.unmemoize', ko.memoization.unmemoize);
  81.853 +ko.exportSymbol('memoization.parseMemoText', ko.memoization.parseMemoText);
  81.854 +ko.exportSymbol('memoization.unmemoizeDomNodeAndDescendants', ko.memoization.unmemoizeDomNodeAndDescendants);
  81.855 +ko.extenders = {
  81.856 +    'throttle': function(target, timeout) {
  81.857 +        // Throttling means two things:
  81.858 +
  81.859 +        // (1) For dependent observables, we throttle *evaluations* so that, no matter how fast its dependencies
  81.860 +        //     notify updates, the target doesn't re-evaluate (and hence doesn't notify) faster than a certain rate
  81.861 +        target['throttleEvaluation'] = timeout;
  81.862 +
  81.863 +        // (2) For writable targets (observables, or writable dependent observables), we throttle *writes*
  81.864 +        //     so the target cannot change value synchronously or faster than a certain rate
  81.865 +        var writeTimeoutInstance = null;
  81.866 +        return ko.dependentObservable({
  81.867 +            'read': target,
  81.868 +            'write': function(value) {
  81.869 +                clearTimeout(writeTimeoutInstance);
  81.870 +                writeTimeoutInstance = setTimeout(function() {
  81.871 +                    target(value);
  81.872 +                }, timeout);
  81.873 +            }
  81.874 +        });
  81.875 +    },
  81.876 +
  81.877 +    'notify': function(target, notifyWhen) {
  81.878 +        target["equalityComparer"] = notifyWhen == "always"
  81.879 +            ? function() { return false } // Treat all values as not equal
  81.880 +            : ko.observable["fn"]["equalityComparer"];
  81.881 +        return target;
  81.882 +    }
  81.883 +};
  81.884 +
  81.885 +function applyExtenders(requestedExtenders) {
  81.886 +    var target = this;
  81.887 +    if (requestedExtenders) {
  81.888 +        for (var key in requestedExtenders) {
  81.889 +            var extenderHandler = ko.extenders[key];
  81.890 +            if (typeof extenderHandler == 'function') {
  81.891 +                target = extenderHandler(target, requestedExtenders[key]);
  81.892 +            }
  81.893 +        }
  81.894 +    }
  81.895 +    return target;
  81.896 +}
  81.897 +
  81.898 +ko.exportSymbol('extenders', ko.extenders);
  81.899 +
  81.900 +ko.subscription = function (target, callback, disposeCallback) {
  81.901 +    this.target = target;
  81.902 +    this.callback = callback;
  81.903 +    this.disposeCallback = disposeCallback;
  81.904 +    ko.exportProperty(this, 'dispose', this.dispose);
  81.905 +};
  81.906 +ko.subscription.prototype.dispose = function () {
  81.907 +    this.isDisposed = true;
  81.908 +    this.disposeCallback();
  81.909 +};
  81.910 +
  81.911 +ko.subscribable = function () {
  81.912 +    this._subscriptions = {};
  81.913 +
  81.914 +    ko.utils.extend(this, ko.subscribable['fn']);
  81.915 +    ko.exportProperty(this, 'subscribe', this.subscribe);
  81.916 +    ko.exportProperty(this, 'extend', this.extend);
  81.917 +    ko.exportProperty(this, 'getSubscriptionsCount', this.getSubscriptionsCount);
  81.918 +}
  81.919 +
  81.920 +var defaultEvent = "change";
  81.921 +
  81.922 +ko.subscribable['fn'] = {
  81.923 +    subscribe: function (callback, callbackTarget, event) {
  81.924 +        event = event || defaultEvent;
  81.925 +        var boundCallback = callbackTarget ? callback.bind(callbackTarget) : callback;
  81.926 +
  81.927 +        var subscription = new ko.subscription(this, boundCallback, function () {
  81.928 +            ko.utils.arrayRemoveItem(this._subscriptions[event], subscription);
  81.929 +        }.bind(this));
  81.930 +
  81.931 +        if (!this._subscriptions[event])
  81.932 +            this._subscriptions[event] = [];
  81.933 +        this._subscriptions[event].push(subscription);
  81.934 +        return subscription;
  81.935 +    },
  81.936 +
  81.937 +    "notifySubscribers": function (valueToNotify, event) {
  81.938 +        event = event || defaultEvent;
  81.939 +        if (this._subscriptions[event]) {
  81.940 +            ko.dependencyDetection.ignore(function() {
  81.941 +                ko.utils.arrayForEach(this._subscriptions[event].slice(0), function (subscription) {
  81.942 +                    // In case a subscription was disposed during the arrayForEach cycle, check
  81.943 +                    // for isDisposed on each subscription before invoking its callback
  81.944 +                    if (subscription && (subscription.isDisposed !== true))
  81.945 +                        subscription.callback(valueToNotify);
  81.946 +                });
  81.947 +            }, this);
  81.948 +        }
  81.949 +    },
  81.950 +
  81.951 +    getSubscriptionsCount: function () {
  81.952 +        var total = 0;
  81.953 +        for (var eventName in this._subscriptions) {
  81.954 +            if (this._subscriptions.hasOwnProperty(eventName))
  81.955 +                total += this._subscriptions[eventName].length;
  81.956 +        }
  81.957 +        return total;
  81.958 +    },
  81.959 +
  81.960 +    extend: applyExtenders
  81.961 +};
  81.962 +
  81.963 +
  81.964 +ko.isSubscribable = function (instance) {
  81.965 +    return typeof instance.subscribe == "function" && typeof instance["notifySubscribers"] == "function";
  81.966 +};
  81.967 +
  81.968 +ko.exportSymbol('subscribable', ko.subscribable);
  81.969 +ko.exportSymbol('isSubscribable', ko.isSubscribable);
  81.970 +
  81.971 +ko.dependencyDetection = (function () {
  81.972 +    var _frames = [];
  81.973 +
  81.974 +    return {
  81.975 +        begin: function (callback) {
  81.976 +            _frames.push({ callback: callback, distinctDependencies:[] });
  81.977 +        },
  81.978 +
  81.979 +        end: function () {
  81.980 +            _frames.pop();
  81.981 +        },
  81.982 +
  81.983 +        registerDependency: function (subscribable) {
  81.984 +            if (!ko.isSubscribable(subscribable))
  81.985 +                throw new Error("Only subscribable things can act as dependencies");
  81.986 +            if (_frames.length > 0) {
  81.987 +                var topFrame = _frames[_frames.length - 1];
  81.988 +                if (!topFrame || ko.utils.arrayIndexOf(topFrame.distinctDependencies, subscribable) >= 0)
  81.989 +                    return;
  81.990 +                topFrame.distinctDependencies.push(subscribable);
  81.991 +                topFrame.callback(subscribable);
  81.992 +            }
  81.993 +        },
  81.994 +
  81.995 +        ignore: function(callback, callbackTarget, callbackArgs) {
  81.996 +            try {
  81.997 +                _frames.push(null);
  81.998 +                return callback.apply(callbackTarget, callbackArgs || []);
  81.999 +            } finally {
 81.1000 +                _frames.pop();
 81.1001 +            }
 81.1002 +        }
 81.1003 +    };
 81.1004 +})();
 81.1005 +var primitiveTypes = { 'undefined':true, 'boolean':true, 'number':true, 'string':true };
 81.1006 +
 81.1007 +ko.observable = function (initialValue) {
 81.1008 +    var _latestValue = initialValue;
 81.1009 +
 81.1010 +    function observable() {
 81.1011 +        if (arguments.length > 0) {
 81.1012 +            // Write
 81.1013 +
 81.1014 +            // Ignore writes if the value hasn't changed
 81.1015 +            if ((!observable['equalityComparer']) || !observable['equalityComparer'](_latestValue, arguments[0])) {
 81.1016 +                observable.valueWillMutate();
 81.1017 +                _latestValue = arguments[0];
 81.1018 +                if (DEBUG) observable._latestValue = _latestValue;
 81.1019 +                observable.valueHasMutated();
 81.1020 +            }
 81.1021 +            return this; // Permits chained assignments
 81.1022 +        }
 81.1023 +        else {
 81.1024 +            // Read
 81.1025 +            ko.dependencyDetection.registerDependency(observable); // The caller only needs to be notified of changes if they did a "read" operation
 81.1026 +            return _latestValue;
 81.1027 +        }
 81.1028 +    }
 81.1029 +    if (DEBUG) observable._latestValue = _latestValue;
 81.1030 +    ko.subscribable.call(observable);
 81.1031 +    observable.peek = function() { return _latestValue };
 81.1032 +    observable.valueHasMutated = function () { observable["notifySubscribers"](_latestValue); }
 81.1033 +    observable.valueWillMutate = function () { observable["notifySubscribers"](_latestValue, "beforeChange"); }
 81.1034 +    ko.utils.extend(observable, ko.observable['fn']);
 81.1035 +
 81.1036 +    ko.exportProperty(observable, 'peek', observable.peek);
 81.1037 +    ko.exportProperty(observable, "valueHasMutated", observable.valueHasMutated);
 81.1038 +    ko.exportProperty(observable, "valueWillMutate", observable.valueWillMutate);
 81.1039 +
 81.1040 +    return observable;
 81.1041 +}
 81.1042 +
 81.1043 +ko.observable['fn'] = {
 81.1044 +    "equalityComparer": function valuesArePrimitiveAndEqual(a, b) {
 81.1045 +        var oldValueIsPrimitive = (a === null) || (typeof(a) in primitiveTypes);
 81.1046 +        return oldValueIsPrimitive ? (a === b) : false;
 81.1047 +    }
 81.1048 +};
 81.1049 +
 81.1050 +var protoProperty = ko.observable.protoProperty = "__ko_proto__";
 81.1051 +ko.observable['fn'][protoProperty] = ko.observable;
 81.1052 +
 81.1053 +ko.hasPrototype = function(instance, prototype) {
 81.1054 +    if ((instance === null) || (instance === undefined) || (instance[protoProperty] === undefined)) return false;
 81.1055 +    if (instance[protoProperty] === prototype) return true;
 81.1056 +    return ko.hasPrototype(instance[protoProperty], prototype); // Walk the prototype chain
 81.1057 +};
 81.1058 +
 81.1059 +ko.isObservable = function (instance) {
 81.1060 +    return ko.hasPrototype(instance, ko.observable);
 81.1061 +}
 81.1062 +ko.isWriteableObservable = function (instance) {
 81.1063 +    // Observable
 81.1064 +    if ((typeof instance == "function") && instance[protoProperty] === ko.observable)
 81.1065 +        return true;
 81.1066 +    // Writeable dependent observable
 81.1067 +    if ((typeof instance == "function") && (instance[protoProperty] === ko.dependentObservable) && (instance.hasWriteFunction))
 81.1068 +        return true;
 81.1069 +    // Anything else
 81.1070 +    return false;
 81.1071 +}
 81.1072 +
 81.1073 +
 81.1074 +ko.exportSymbol('observable', ko.observable);
 81.1075 +ko.exportSymbol('isObservable', ko.isObservable);
 81.1076 +ko.exportSymbol('isWriteableObservable', ko.isWriteableObservable);
 81.1077 +ko.observableArray = function (initialValues) {
 81.1078 +    if (arguments.length == 0) {
 81.1079 +        // Zero-parameter constructor initializes to empty array
 81.1080 +        initialValues = [];
 81.1081 +    }
 81.1082 +    if ((initialValues !== null) && (initialValues !== undefined) && !('length' in initialValues))
 81.1083 +        throw new Error("The argument passed when initializing an observable array must be an array, or null, or undefined.");
 81.1084 +
 81.1085 +    var result = ko.observable(initialValues);
 81.1086 +    ko.utils.extend(result, ko.observableArray['fn']);
 81.1087 +    return result;
 81.1088 +}
 81.1089 +
 81.1090 +ko.observableArray['fn'] = {
 81.1091 +    'remove': function (valueOrPredicate) {
 81.1092 +        var underlyingArray = this.peek();
 81.1093 +        var removedValues = [];
 81.1094 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
 81.1095 +        for (var i = 0; i < underlyingArray.length; i++) {
 81.1096 +            var value = underlyingArray[i];
 81.1097 +            if (predicate(value)) {
 81.1098 +                if (removedValues.length === 0) {
 81.1099 +                    this.valueWillMutate();
 81.1100 +                }
 81.1101 +                removedValues.push(value);
 81.1102 +                underlyingArray.splice(i, 1);
 81.1103 +                i--;
 81.1104 +            }
 81.1105 +        }
 81.1106 +        if (removedValues.length) {
 81.1107 +            this.valueHasMutated();
 81.1108 +        }
 81.1109 +        return removedValues;
 81.1110 +    },
 81.1111 +
 81.1112 +    'removeAll': function (arrayOfValues) {
 81.1113 +        // If you passed zero args, we remove everything
 81.1114 +        if (arrayOfValues === undefined) {
 81.1115 +            var underlyingArray = this.peek();
 81.1116 +            var allValues = underlyingArray.slice(0);
 81.1117 +            this.valueWillMutate();
 81.1118 +            underlyingArray.splice(0, underlyingArray.length);
 81.1119 +            this.valueHasMutated();
 81.1120 +            return allValues;
 81.1121 +        }
 81.1122 +        // If you passed an arg, we interpret it as an array of entries to remove
 81.1123 +        if (!arrayOfValues)
 81.1124 +            return [];
 81.1125 +        return this['remove'](function (value) {
 81.1126 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
 81.1127 +        });
 81.1128 +    },
 81.1129 +
 81.1130 +    'destroy': function (valueOrPredicate) {
 81.1131 +        var underlyingArray = this.peek();
 81.1132 +        var predicate = typeof valueOrPredicate == "function" ? valueOrPredicate : function (value) { return value === valueOrPredicate; };
 81.1133 +        this.valueWillMutate();
 81.1134 +        for (var i = underlyingArray.length - 1; i >= 0; i--) {
 81.1135 +            var value = underlyingArray[i];
 81.1136 +            if (predicate(value))
 81.1137 +                underlyingArray[i]["_destroy"] = true;
 81.1138 +        }
 81.1139 +        this.valueHasMutated();
 81.1140 +    },
 81.1141 +
 81.1142 +    'destroyAll': function (arrayOfValues) {
 81.1143 +        // If you passed zero args, we destroy everything
 81.1144 +        if (arrayOfValues === undefined)
 81.1145 +            return this['destroy'](function() { return true });
 81.1146 +
 81.1147 +        // If you passed an arg, we interpret it as an array of entries to destroy
 81.1148 +        if (!arrayOfValues)
 81.1149 +            return [];
 81.1150 +        return this['destroy'](function (value) {
 81.1151 +            return ko.utils.arrayIndexOf(arrayOfValues, value) >= 0;
 81.1152 +        });
 81.1153 +    },
 81.1154 +
 81.1155 +    'indexOf': function (item) {
 81.1156 +        var underlyingArray = this();
 81.1157 +        return ko.utils.arrayIndexOf(underlyingArray, item);
 81.1158 +    },
 81.1159 +
 81.1160 +    'replace': function(oldItem, newItem) {
 81.1161 +        var index = this['indexOf'](oldItem);
 81.1162 +        if (index >= 0) {
 81.1163 +            this.valueWillMutate();
 81.1164 +            this.peek()[index] = newItem;
 81.1165 +            this.valueHasMutated();
 81.1166 +        }
 81.1167 +    }
 81.1168 +}
 81.1169 +
 81.1170 +// Populate ko.observableArray.fn with read/write functions from native arrays
 81.1171 +// Important: Do not add any additional functions here that may reasonably be used to *read* data from the array
 81.1172 +// because we'll eval them without causing subscriptions, so ko.computed output could end up getting stale
 81.1173 +ko.utils.arrayForEach(["pop", "push", "reverse", "shift", "sort", "splice", "unshift"], function (methodName) {
 81.1174 +    ko.observableArray['fn'][methodName] = function () {
 81.1175 +        // Use "peek" to avoid creating a subscription in any computed that we're executing in the context of
 81.1176 +        // (for consistency with mutating regular observables)
 81.1177 +        var underlyingArray = this.peek();
 81.1178 +        this.valueWillMutate();
 81.1179 +        var methodCallResult = underlyingArray[methodName].apply(underlyingArray, arguments);
 81.1180 +        this.valueHasMutated();
 81.1181 +        return methodCallResult;
 81.1182 +    };
 81.1183 +});
 81.1184 +
 81.1185 +// Populate ko.observableArray.fn with read-only functions from native arrays
 81.1186 +ko.utils.arrayForEach(["slice"], function (methodName) {
 81.1187 +    ko.observableArray['fn'][methodName] = function () {
 81.1188 +        var underlyingArray = this();
 81.1189 +        return underlyingArray[methodName].apply(underlyingArray, arguments);
 81.1190 +    };
 81.1191 +});
 81.1192 +
 81.1193 +ko.exportSymbol('observableArray', ko.observableArray);
 81.1194 +ko.dependentObservable = function (evaluatorFunctionOrOptions, evaluatorFunctionTarget, options) {
 81.1195 +    var _latestValue,
 81.1196 +        _hasBeenEvaluated = false,
 81.1197 +        _isBeingEvaluated = false,
 81.1198 +        readFunction = evaluatorFunctionOrOptions;
 81.1199 +
 81.1200 +    if (readFunction && typeof readFunction == "object") {
 81.1201 +        // Single-parameter syntax - everything is on this "options" param
 81.1202 +        options = readFunction;
 81.1203 +        readFunction = options["read"];
 81.1204 +    } else {
 81.1205 +        // Multi-parameter syntax - construct the options according to the params passed
 81.1206 +        options = options || {};
 81.1207 +        if (!readFunction)
 81.1208 +            readFunction = options["read"];
 81.1209 +    }
 81.1210 +    if (typeof readFunction != "function")
 81.1211 +        throw new Error("Pass a function that returns the value of the ko.computed");
 81.1212 +
 81.1213 +    function addSubscriptionToDependency(subscribable) {
 81.1214 +        _subscriptionsToDependencies.push(subscribable.subscribe(evaluatePossiblyAsync));
 81.1215 +    }
 81.1216 +
 81.1217 +    function disposeAllSubscriptionsToDependencies() {
 81.1218 +        ko.utils.arrayForEach(_subscriptionsToDependencies, function (subscription) {
 81.1219 +            subscription.dispose();
 81.1220 +        });
 81.1221 +        _subscriptionsToDependencies = [];
 81.1222 +    }
 81.1223 +
 81.1224 +    function evaluatePossiblyAsync() {
 81.1225 +        var throttleEvaluationTimeout = dependentObservable['throttleEvaluation'];
 81.1226 +        if (throttleEvaluationTimeout && throttleEvaluationTimeout >= 0) {
 81.1227 +            clearTimeout(evaluationTimeoutInstance);
 81.1228 +            evaluationTimeoutInstance = setTimeout(evaluateImmediate, throttleEvaluationTimeout);
 81.1229 +        } else
 81.1230 +            evaluateImmediate();
 81.1231 +    }
 81.1232 +
 81.1233 +    function evaluateImmediate() {
 81.1234 +        if (_isBeingEvaluated) {
 81.1235 +            // If the evaluation of a ko.computed causes side effects, it's possible that it will trigger its own re-evaluation.
 81.1236 +            // This is not desirable (it's hard for a developer to realise a chain of dependencies might cause this, and they almost
 81.1237 +            // certainly didn't intend infinite re-evaluations). So, for predictability, we simply prevent ko.computeds from causing
 81.1238 +            // their own re-evaluation. Further discussion at https://github.com/SteveSanderson/knockout/pull/387
 81.1239 +            return;
 81.1240 +        }
 81.1241 +
 81.1242 +        // Don't dispose on first evaluation, because the "disposeWhen" callback might
 81.1243 +        // e.g., dispose when the associated DOM element isn't in the doc, and it's not
 81.1244 +        // going to be in the doc until *after* the first evaluation
 81.1245 +        if (_hasBeenEvaluated && disposeWhen()) {
 81.1246 +            dispose();
 81.1247 +            return;
 81.1248 +        }
 81.1249 +
 81.1250 +        _isBeingEvaluated = true;
 81.1251 +        try {
 81.1252 +            // Initially, we assume that none of the subscriptions are still being used (i.e., all are candidates for disposal).
 81.1253 +            // Then, during evaluation, we cross off any that are in fact still being used.
 81.1254 +            var disposalCandidates = ko.utils.arrayMap(_subscriptionsToDependencies, function(item) {return item.target;});
 81.1255 +
 81.1256 +            ko.dependencyDetection.begin(function(subscribable) {
 81.1257 +                var inOld;
 81.1258 +                if ((inOld = ko.utils.arrayIndexOf(disposalCandidates, subscribable)) >= 0)
 81.1259 +                    disposalCandidates[inOld] = undefined; // Don't want to dispose this subscription, as it's still being used
 81.1260 +                else
 81.1261 +                    addSubscriptionToDependency(subscribable); // Brand new subscription - add it
 81.1262 +            });
 81.1263 +
 81.1264 +            var newValue = readFunction.call(evaluatorFunctionTarget);
 81.1265 +
 81.1266 +            // For each subscription no longer being used, remove it from the active subscriptions list and dispose it
 81.1267 +            for (var i = disposalCandidates.length - 1; i >= 0; i--) {
 81.1268 +                if (disposalCandidates[i])
 81.1269 +                    _subscriptionsToDependencies.splice(i, 1)[0].dispose();
 81.1270 +            }
 81.1271 +            _hasBeenEvaluated = true;
 81.1272 +
 81.1273 +            dependentObservable["notifySubscribers"](_latestValue, "beforeChange");
 81.1274 +            _latestValue = newValue;
 81.1275 +            if (DEBUG) dependentObservable._latestValue = _latestValue;
 81.1276 +        } finally {
 81.1277 +            ko.dependencyDetection.end();
 81.1278 +        }
 81.1279 +
 81.1280 +        dependentObservable["notifySubscribers"](_latestValue);
 81.1281 +        _isBeingEvaluated = false;
 81.1282 +        if (!_subscriptionsToDependencies.length)
 81.1283 +            dispose();
 81.1284 +    }
 81.1285 +
 81.1286 +    function dependentObservable() {
 81.1287 +        if (arguments.length > 0) {
 81.1288 +            if (typeof writeFunction === "function") {
 81.1289 +                // Writing a value
 81.1290 +                writeFunction.apply(evaluatorFunctionTarget, arguments);
 81.1291 +            } else {
 81.1292 +                throw new Error("Cannot write a value to a ko.computed unless you specify a 'write' option. If you wish to read the current value, don't pass any parameters.");
 81.1293 +            }
 81.1294 +            return this; // Permits chained assignments
 81.1295 +        } else {
 81.1296 +            // Reading the value
 81.1297 +            if (!_hasBeenEvaluated)
 81.1298 +                evaluateImmediate();
 81.1299 +            ko.dependencyDetection.registerDependency(dependentObservable);
 81.1300 +            return _latestValue;
 81.1301 +        }
 81.1302 +    }
 81.1303 +
 81.1304 +    function peek() {
 81.1305 +        if (!_hasBeenEvaluated)
 81.1306 +            evaluateImmediate();
 81.1307 +        return _latestValue;
 81.1308 +    }
 81.1309 +
 81.1310 +    function isActive() {
 81.1311 +        return !_hasBeenEvaluated || _subscriptionsToDependencies.length > 0;
 81.1312 +    }
 81.1313 +
 81.1314 +    // By here, "options" is always non-null
 81.1315 +    var writeFunction = options["write"],
 81.1316 +        disposeWhenNodeIsRemoved = options["disposeWhenNodeIsRemoved"] || options.disposeWhenNodeIsRemoved || null,
 81.1317 +        disposeWhen = options["disposeWhen"] || options.disposeWhen || function() { return false; },
 81.1318 +        dispose = disposeAllSubscriptionsToDependencies,
 81.1319 +        _subscriptionsToDependencies = [],
 81.1320 +        evaluationTimeoutInstance = null;
 81.1321 +
 81.1322 +    if (!evaluatorFunctionTarget)
 81.1323 +        evaluatorFunctionTarget = options["owner"];
 81.1324 +
 81.1325 +    dependentObservable.peek = peek;
 81.1326 +    dependentObservable.getDependenciesCount = function () { return _subscriptionsToDependencies.length; };
 81.1327 +    dependentObservable.hasWriteFunction = typeof options["write"] === "function";
 81.1328 +    dependentObservable.dispose = function () { dispose(); };
 81.1329 +    dependentObservable.isActive = isActive;
 81.1330 +    dependentObservable.valueHasMutated = function() {
 81.1331 +        _hasBeenEvaluated = false;
 81.1332 +        evaluateImmediate();
 81.1333 +    };
 81.1334 +
 81.1335 +    ko.subscribable.call(dependentObservable);
 81.1336 +    ko.utils.extend(dependentObservable, ko.dependentObservable['fn']);
 81.1337 +
 81.1338 +    ko.exportProperty(dependentObservable, 'peek', dependentObservable.peek);
 81.1339 +    ko.exportProperty(dependentObservable, 'dispose', dependentObservable.dispose);
 81.1340 +    ko.exportProperty(dependentObservable, 'isActive', dependentObservable.isActive);
 81.1341 +    ko.exportProperty(dependentObservable, 'getDependenciesCount', dependentObservable.getDependenciesCount);
 81.1342 +
 81.1343 +    // Evaluate, unless deferEvaluation is true
 81.1344 +    if (options['deferEvaluation'] !== true)
 81.1345 +        evaluateImmediate();
 81.1346 +
 81.1347 +    // Build "disposeWhenNodeIsRemoved" and "disposeWhenNodeIsRemovedCallback" option values.
 81.1348 +    // But skip if isActive is false (there will never be any dependencies to dispose).
 81.1349 +    // (Note: "disposeWhenNodeIsRemoved" option both proactively disposes as soon as the node is removed using ko.removeNode(),
 81.1350 +    // plus adds a "disposeWhen" callback that, on each evaluation, disposes if the node was removed by some other means.)
 81.1351 +    if (disposeWhenNodeIsRemoved && isActive()) {
 81.1352 +        dispose = function() {
 81.1353 +            ko.utils.domNodeDisposal.removeDisposeCallback(disposeWhenNodeIsRemoved, arguments.callee);
 81.1354 +            disposeAllSubscriptionsToDependencies();
 81.1355 +        };
 81.1356 +        ko.utils.domNodeDisposal.addDisposeCallback(disposeWhenNodeIsRemoved, dispose);
 81.1357 +        var existingDisposeWhenFunction = disposeWhen;
 81.1358 +        disposeWhen = function () {
 81.1359 +            return !ko.utils.domNodeIsAttachedToDocument(disposeWhenNodeIsRemoved) || existingDisposeWhenFunction();
 81.1360 +        }
 81.1361 +    }
 81.1362 +
 81.1363 +    return dependentObservable;
 81.1364 +};
 81.1365 +
 81.1366 +ko.isComputed = function(instance) {
 81.1367 +    return ko.hasPrototype(instance, ko.dependentObservable);
 81.1368 +};
 81.1369 +
 81.1370 +var protoProp = ko.observable.protoProperty; // == "__ko_proto__"
 81.1371 +ko.dependentObservable[protoProp] = ko.observable;
 81.1372 +
 81.1373 +ko.dependentObservable['fn'] = {};
 81.1374 +ko.dependentObservable['fn'][protoProp] = ko.dependentObservable;
 81.1375 +
 81.1376 +ko.exportSymbol('dependentObservable', ko.dependentObservable);
 81.1377 +ko.exportSymbol('computed', ko.dependentObservable); // Make "ko.computed" an alias for "ko.dependentObservable"
 81.1378 +ko.exportSymbol('isComputed', ko.isComputed);
 81.1379 +
 81.1380 +(function() {
 81.1381 +    var maxNestedObservableDepth = 10; // Escape the (unlikely) pathalogical case where an observable's current value is itself (or similar reference cycle)
 81.1382 +
 81.1383 +    ko.toJS = function(rootObject) {
 81.1384 +        if (arguments.length == 0)
 81.1385 +            throw new Error("When calling ko.toJS, pass the object you want to convert.");
 81.1386 +
 81.1387 +        // We just unwrap everything at every level in the object graph
 81.1388 +        return mapJsObjectGraph(rootObject, function(valueToMap) {
 81.1389 +            // Loop because an observable's value might in turn be another observable wrapper
 81.1390 +            for (var i = 0; ko.isObservable(valueToMap) && (i < maxNestedObservableDepth); i++)
 81.1391 +                valueToMap = valueToMap();
 81.1392 +            return valueToMap;
 81.1393 +        });
 81.1394 +    };
 81.1395 +
 81.1396 +    ko.toJSON = function(rootObject, replacer, space) {     // replacer and space are optional
 81.1397 +        var plainJavaScriptObject = ko.toJS(rootObject);
 81.1398 +        return ko.utils.stringifyJson(plainJavaScriptObject, replacer, space);
 81.1399 +    };
 81.1400 +
 81.1401 +    function mapJsObjectGraph(rootObject, mapInputCallback, visitedObjects) {
 81.1402 +        visitedObjects = visitedObjects || new objectLookup();
 81.1403 +
 81.1404 +        rootObject = mapInputCallback(rootObject);
 81.1405 +        var canHaveProperties = (typeof rootObject == "object") && (rootObject !== null) && (rootObject !== undefined) && (!(rootObject instanceof Date));
 81.1406 +        if (!canHaveProperties)
 81.1407 +            return rootObject;
 81.1408 +
 81.1409 +        var outputProperties = rootObject instanceof Array ? [] : {};
 81.1410 +        visitedObjects.save(rootObject, outputProperties);
 81.1411 +
 81.1412 +        visitPropertiesOrArrayEntries(rootObject, function(indexer) {
 81.1413 +            var propertyValue = mapInputCallback(rootObject[indexer]);
 81.1414 +
 81.1415 +            switch (typeof propertyValue) {
 81.1416 +                case "boolean":
 81.1417 +                case "number":
 81.1418 +                case "string":
 81.1419 +                case "function":
 81.1420 +                    outputProperties[indexer] = propertyValue;
 81.1421 +                    break;
 81.1422 +                case "object":
 81.1423 +                case "undefined":
 81.1424 +                    var previouslyMappedValue = visitedObjects.get(propertyValue);
 81.1425 +                    outputProperties[indexer] = (previouslyMappedValue !== undefined)
 81.1426 +                        ? previouslyMappedValue
 81.1427 +                        : mapJsObjectGraph(propertyValue, mapInputCallback, visitedObjects);
 81.1428 +                    break;
 81.1429 +            }
 81.1430 +        });
 81.1431 +
 81.1432 +        return outputProperties;
 81.1433 +    }
 81.1434 +
 81.1435 +    function visitPropertiesOrArrayEntries(rootObject, visitorCallback) {
 81.1436 +        if (rootObject instanceof Array) {
 81.1437 +            for (var i = 0; i < rootObject.length; i++)
 81.1438 +                visitorCallback(i);
 81.1439 +
 81.1440 +            // For arrays, also respect toJSON property for custom mappings (fixes #278)
 81.1441 +            if (typeof rootObject['toJSON'] == 'function')
 81.1442 +                visitorCallback('toJSON');
 81.1443 +        } else {
 81.1444 +            for (var propertyName in rootObject)
 81.1445 +                visitorCallback(propertyName);
 81.1446 +        }
 81.1447 +    };
 81.1448 +
 81.1449 +    function objectLookup() {
 81.1450 +        var keys = [];
 81.1451 +        var values = [];
 81.1452 +        this.save = function(key, value) {
 81.1453 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
 81.1454 +            if (existingIndex >= 0)
 81.1455 +                values[existingIndex] = value;
 81.1456 +            else {
 81.1457 +                keys.push(key);
 81.1458 +                values.push(value);
 81.1459 +            }
 81.1460 +        };
 81.1461 +        this.get = function(key) {
 81.1462 +            var existingIndex = ko.utils.arrayIndexOf(keys, key);
 81.1463 +            return (existingIndex >= 0) ? values[existingIndex] : undefined;
 81.1464 +        };
 81.1465 +    };
 81.1466 +})();
 81.1467 +
 81.1468 +ko.exportSymbol('toJS', ko.toJS);
 81.1469 +ko.exportSymbol('toJSON', ko.toJSON);
 81.1470 +(function () {
 81.1471 +    var hasDomDataExpandoProperty = '__ko__hasDomDataOptionValue__';
 81.1472 +
 81.1473 +    // Normally, SELECT elements and their OPTIONs can only take value of type 'string' (because the values
 81.1474 +    // are stored on DOM attributes). ko.selectExtensions provides a way for SELECTs/OPTIONs to have values
 81.1475 +    // that are arbitrary objects. This is very convenient when implementing things like cascading dropdowns.
 81.1476 +    ko.selectExtensions = {
 81.1477 +        readValue : function(element) {
 81.1478 +            switch (ko.utils.tagNameLower(element)) {
 81.1479 +                case 'option':
 81.1480 +                    if (element[hasDomDataExpandoProperty] === true)
 81.1481 +                        return ko.utils.domData.get(element, ko.bindingHandlers.options.optionValueDomDataKey);
 81.1482 +                    return ko.utils.ieVersion <= 7
 81.1483 +                        ? (element.getAttributeNode('value').specified ? element.value : element.text)
 81.1484 +                        : element.value;
 81.1485 +                case 'select':
 81.1486 +                    return element.selectedIndex >= 0 ? ko.selectExtensions.readValue(element.options[element.selectedIndex]) : undefined;
 81.1487 +                default:
 81.1488 +                    return element.value;
 81.1489 +            }
 81.1490 +        },
 81.1491 +
 81.1492 +        writeValue: function(element, value) {
 81.1493 +            switch (ko.utils.tagNameLower(element)) {
 81.1494 +                case 'option':
 81.1495 +                    switch(typeof value) {
 81.1496 +                        case "string":
 81.1497 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, undefined);
 81.1498 +                            if (hasDomDataExpandoProperty in element) { // IE <= 8 throws errors if you delete non-existent properties from a DOM node
 81.1499 +                                delete element[hasDomDataExpandoProperty];
 81.1500 +                            }
 81.1501 +                            element.value = value;
 81.1502 +                            break;
 81.1503 +                        default:
 81.1504 +                            // Store arbitrary object using DomData
 81.1505 +                            ko.utils.domData.set(element, ko.bindingHandlers.options.optionValueDomDataKey, value);
 81.1506 +                            element[hasDomDataExpandoProperty] = true;
 81.1507 +
 81.1508 +                            // Special treatment of numbers is just for backward compatibility. KO 1.2.1 wrote numerical values to element.value.
 81.1509 +                            element.value = typeof value === "number" ? value : "";
 81.1510 +                            break;
 81.1511 +                    }
 81.1512 +                    break;
 81.1513 +                case 'select':
 81.1514 +                    for (var i = element.options.length - 1; i >= 0; i--) {
 81.1515 +                        if (ko.selectExtensions.readValue(element.options[i]) == value) {
 81.1516 +                            element.selectedIndex = i;
 81.1517 +                            break;
 81.1518 +                        }
 81.1519 +                    }
 81.1520 +                    break;
 81.1521 +                default:
 81.1522 +                    if ((value === null) || (value === undefined))
 81.1523 +                        value = "";
 81.1524 +                    element.value = value;
 81.1525 +                    break;
 81.1526 +            }
 81.1527 +        }
 81.1528 +    };
 81.1529 +})();
 81.1530 +
 81.1531 +ko.exportSymbol('selectExtensions', ko.selectExtensions);
 81.1532 +ko.exportSymbol('selectExtensions.readValue', ko.selectExtensions.readValue);
 81.1533 +ko.exportSymbol('selectExtensions.writeValue', ko.selectExtensions.writeValue);
 81.1534 +ko.expressionRewriting = (function () {
 81.1535 +    var restoreCapturedTokensRegex = /\@ko_token_(\d+)\@/g;
 81.1536 +    var javaScriptReservedWords = ["true", "false"];
 81.1537 +
 81.1538 +    // Matches something that can be assigned to--either an isolated identifier or something ending with a property accessor
 81.1539 +    // This is designed to be simple and avoid false negatives, but could produce false positives (e.g., a+b.c).
 81.1540 +    var javaScriptAssignmentTarget = /^(?:[$_a-z][$\w]*|(.+)(\.\s*[$_a-z][$\w]*|\[.+\]))$/i;
 81.1541 +
 81.1542 +    function restoreTokens(string, tokens) {
 81.1543 +        var prevValue = null;
 81.1544 +        while (string != prevValue) { // Keep restoring tokens until it no longer makes a difference (they may be nested)
 81.1545 +            prevValue = string;
 81.1546 +            string = string.replace(restoreCapturedTokensRegex, function (match, tokenIndex) {
 81.1547 +                return tokens[tokenIndex];
 81.1548 +            });
 81.1549 +        }
 81.1550 +        return string;
 81.1551 +    }
 81.1552 +
 81.1553 +    function getWriteableValue(expression) {
 81.1554 +        if (ko.utils.arrayIndexOf(javaScriptReservedWords, ko.utils.stringTrim(expression).toLowerCase()) >= 0)
 81.1555 +            return false;
 81.1556 +        var match = expression.match(javaScriptAssignmentTarget);
 81.1557 +        return match === null ? false : match[1] ? ('Object(' + match[1] + ')' + match[2]) : expression;
 81.1558 +    }
 81.1559 +
 81.1560 +    function ensureQuoted(key) {
 81.1561 +        var trimmedKey = ko.utils.stringTrim(key);
 81.1562 +        switch (trimmedKey.length && trimmedKey.charAt(0)) {
 81.1563 +            case "'":
 81.1564 +            case '"':
 81.1565 +                return key;
 81.1566 +            default:
 81.1567 +                return "'" + trimmedKey + "'";
 81.1568 +        }
 81.1569 +    }
 81.1570 +
 81.1571 +    return {
 81.1572 +        bindingRewriteValidators: [],
 81.1573 +
 81.1574 +        parseObjectLiteral: function(objectLiteralString) {
 81.1575 +            // A full tokeniser+lexer would add too much weight to this library, so here's a simple parser
 81.1576 +            // that is sufficient just to split an object literal string into a set of top-level key-value pairs
 81.1577 +
 81.1578 +            var str = ko.utils.stringTrim(objectLiteralString);
 81.1579 +            if (str.length < 3)
 81.1580 +                return [];
 81.1581 +            if (str.charAt(0) === "{")// Ignore any braces surrounding the whole object literal
 81.1582 +                str = str.substring(1, str.length - 1);
 81.1583 +
 81.1584 +            // Pull out any string literals and regex literals
 81.1585 +            var tokens = [];
 81.1586 +            var tokenStart = null, tokenEndChar;
 81.1587 +            for (var position = 0; position < str.length; position++) {
 81.1588 +                var c = str.charAt(position);
 81.1589 +                if (tokenStart === null) {
 81.1590 +                    switch (c) {
 81.1591 +                        case '"':
 81.1592 +                        case "'":
 81.1593 +                        case "/":
 81.1594 +                            tokenStart = position;
 81.1595 +                            tokenEndChar = c;
 81.1596 +                            break;
 81.1597 +                    }
 81.1598 +                } else if ((c == tokenEndChar) && (str.charAt(position - 1) !== "\\")) {
 81.1599 +                    var token = str.substring(tokenStart, position + 1);
 81.1600 +                    tokens.push(token);
 81.1601 +                    var replacement = "@ko_token_" + (tokens.length - 1) + "@";
 81.1602 +                    str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
 81.1603 +                    position -= (token.length - replacement.length);
 81.1604 +                    tokenStart = null;
 81.1605 +                }
 81.1606 +            }
 81.1607 +
 81.1608 +            // Next pull out balanced paren, brace, and bracket blocks
 81.1609 +            tokenStart = null;
 81.1610 +            tokenEndChar = null;
 81.1611 +            var tokenDepth = 0, tokenStartChar = null;
 81.1612 +            for (var position = 0; position < str.length; position++) {
 81.1613 +                var c = str.charAt(position);
 81.1614 +                if (tokenStart === null) {
 81.1615 +                    switch (c) {
 81.1616 +                        case "{": tokenStart = position; tokenStartChar = c;
 81.1617 +                                  tokenEndChar = "}";
 81.1618 +                                  break;
 81.1619 +                        case "(": tokenStart = position; tokenStartChar = c;
 81.1620 +                                  tokenEndChar = ")";
 81.1621 +                                  break;
 81.1622 +                        case "[": tokenStart = position; tokenStartChar = c;
 81.1623 +                                  tokenEndChar = "]";
 81.1624 +                                  break;
 81.1625 +                    }
 81.1626 +                }
 81.1627 +
 81.1628 +                if (c === tokenStartChar)
 81.1629 +                    tokenDepth++;
 81.1630 +                else if (c === tokenEndChar) {
 81.1631 +                    tokenDepth--;
 81.1632 +                    if (tokenDepth === 0) {
 81.1633 +                        var token = str.substring(tokenStart, position + 1);
 81.1634 +                        tokens.push(token);
 81.1635 +                        var replacement = "@ko_token_" + (tokens.length - 1) + "@";
 81.1636 +                        str = str.substring(0, tokenStart) + replacement + str.substring(position + 1);
 81.1637 +                        position -= (token.length - replacement.length);
 81.1638 +                        tokenStart = null;
 81.1639 +                    }
 81.1640 +                }
 81.1641 +            }
 81.1642 +
 81.1643 +            // Now we can safely split on commas to get the key/value pairs
 81.1644 +            var result = [];
 81.1645 +            var keyValuePairs = str.split(",");
 81.1646 +            for (var i = 0, j = keyValuePairs.length; i < j; i++) {
 81.1647 +                var pair = keyValuePairs[i];
 81.1648 +                var colonPos = pair.indexOf(":");
 81.1649 +                if ((colonPos > 0) && (colonPos < pair.length - 1)) {
 81.1650 +                    var key = pair.substring(0, colonPos);
 81.1651 +                    var value = pair.substring(colonPos + 1);
 81.1652 +                    result.push({ 'key': restoreTokens(key, tokens), 'value': restoreTokens(value, tokens) });
 81.1653 +                } else {
 81.1654 +                    result.push({ 'unknown': restoreTokens(pair, tokens) });
 81.1655 +                }
 81.1656 +            }
 81.1657 +            return result;
 81.1658 +        },
 81.1659 +
 81.1660 +        preProcessBindings: function (objectLiteralStringOrKeyValueArray) {
 81.1661 +            var keyValueArray = typeof objectLiteralStringOrKeyValueArray === "string"
 81.1662 +                ? ko.expressionRewriting.parseObjectLiteral(objectLiteralStringOrKeyValueArray)
 81.1663 +                : objectLiteralStringOrKeyValueArray;
 81.1664 +            var resultStrings = [], propertyAccessorResultStrings = [];
 81.1665 +
 81.1666 +            var keyValueEntry;
 81.1667 +            for (var i = 0; keyValueEntry = keyValueArray[i]; i++) {
 81.1668 +                if (resultStrings.length > 0)
 81.1669 +                    resultStrings.push(",");
 81.1670 +
 81.1671 +                if (keyValueEntry['key']) {
 81.1672 +                    var quotedKey = ensureQuoted(keyValueEntry['key']), val = keyValueEntry['value'];
 81.1673 +                    resultStrings.push(quotedKey);
 81.1674 +                    resultStrings.push(":");
 81.1675 +                    resultStrings.push(val);
 81.1676 +
 81.1677 +                    if (val = getWriteableValue(ko.utils.stringTrim(val))) {
 81.1678 +                        if (propertyAccessorResultStrings.length > 0)
 81.1679 +                            propertyAccessorResultStrings.push(", ");
 81.1680 +                        propertyAccessorResultStrings.push(quotedKey + " : function(__ko_value) { " + val + " = __ko_value; }");
 81.1681 +                    }
 81.1682 +                } else if (keyValueEntry['unknown']) {
 81.1683 +                    resultStrings.push(keyValueEntry['unknown']);
 81.1684 +                }
 81.1685 +            }
 81.1686 +
 81.1687 +            var combinedResult = resultStrings.join("");
 81.1688 +            if (propertyAccessorResultStrings.length > 0) {
 81.1689 +                var allPropertyAccessors = propertyAccessorResultStrings.join("");
 81.1690 +                combinedResult = combinedResult + ", '_ko_property_writers' : { " + allPropertyAccessors + " } ";
 81.1691 +            }
 81.1692 +
 81.1693 +            return combinedResult;
 81.1694 +        },
 81.1695 +
 81.1696 +        keyValueArrayContainsKey: function(keyValueArray, key) {
 81.1697 +            for (var i = 0; i < keyValueArray.length; i++)
 81.1698 +                if (ko.utils.stringTrim(keyValueArray[i]['key']) == key)
 81.1699 +                    return true;
 81.1700 +            return false;
 81.1701 +        },
 81.1702 +
 81.1703 +        // Internal, private KO utility for updating model properties from within bindings
 81.1704 +        // property:            If the property being updated is (or might be) an observable, pass it here
 81.1705 +        //                      If it turns out to be a writable observable, it will be written to directly
 81.1706 +        // allBindingsAccessor: All bindings in the current execution context.
 81.1707 +        //                      This will be searched for a '_ko_property_writers' property in case you're writing to a non-observable
 81.1708 +        // key:                 The key identifying the property to be written. Example: for { hasFocus: myValue }, write to 'myValue' by specifying the key 'hasFocus'
 81.1709 +        // value:               The value to be written
 81.1710 +        // checkIfDifferent:    If true, and if the property being written is a writable observable, the value will only be written if
 81.1711 +        //                      it is !== existing value on that writable observable
 81.1712 +        writeValueToProperty: function(property, allBindingsAccessor, key, value, checkIfDifferent) {
 81.1713 +            if (!property || !ko.isWriteableObservable(property)) {
 81.1714 +                var propWriters = allBindingsAccessor()['_ko_property_writers'];
 81.1715 +                if (propWriters && propWriters[key])
 81.1716 +                    propWriters[key](value);
 81.1717 +            } else if (!checkIfDifferent || property.peek() !== value) {
 81.1718 +                property(value);
 81.1719 +            }
 81.1720 +        }
 81.1721 +    };
 81.1722 +})();
 81.1723 +
 81.1724 +ko.exportSymbol('expressionRewriting', ko.expressionRewriting);
 81.1725 +ko.exportSymbol('expressionRewriting.bindingRewriteValidators', ko.expressionRewriting.bindingRewriteValidators);
 81.1726 +ko.exportSymbol('expressionRewriting.parseObjectLiteral', ko.expressionRewriting.parseObjectLiteral);
 81.1727 +ko.exportSymbol('expressionRewriting.preProcessBindings', ko.expressionRewriting.preProcessBindings);
 81.1728 +
 81.1729 +// For backward compatibility, define the following aliases. (Previously, these function names were misleading because
 81.1730 +// they referred to JSON specifically, even though they actually work with arbitrary JavaScript object literal expressions.)
 81.1731 +ko.exportSymbol('jsonExpressionRewriting', ko.expressionRewriting);
 81.1732 +ko.exportSymbol('jsonExpressionRewriting.insertPropertyAccessorsIntoJson', ko.expressionRewriting.preProcessBindings);(function() {
 81.1733 +    // "Virtual elements" is an abstraction on top of the usual DOM API which understands the notion that comment nodes
 81.1734 +    // may be used to represent hierarchy (in addition to the DOM's natural hierarchy).
 81.1735 +    // If you call the DOM-manipulating functions on ko.virtualElements, you will be able to read and write the state
 81.1736 +    // of that virtual hierarchy
 81.1737 +    //
 81.1738 +    // The point of all this is to support containerless templates (e.g., <!-- ko foreach:someCollection -->blah<!-- /ko -->)
 81.1739 +    // without having to scatter special cases all over the binding and templating code.
 81.1740 +
 81.1741 +    // IE 9 cannot reliably read the "nodeValue" property of a comment node (see https://github.com/SteveSanderson/knockout/issues/186)
 81.1742 +    // but it does give them a nonstandard alternative property called "text" that it can read reliably. Other browsers don't have that property.
 81.1743 +    // So, use node.text where available, and node.nodeValue elsewhere
 81.1744 +    var commentNodesHaveTextProperty = document.createComment("test").text === "<!--test-->";
 81.1745 +
 81.1746 +    var startCommentRegex = commentNodesHaveTextProperty ? /^<!--\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*-->$/ : /^\s*ko(?:\s+(.+\s*\:[\s\S]*))?\s*$/;
 81.1747 +    var endCommentRegex =   commentNodesHaveTextProperty ? /^<!--\s*\/ko\s*-->$/ : /^\s*\/ko\s*$/;
 81.1748 +    var htmlTagsWithOptionallyClosingChildren = { 'ul': true, 'ol': true };
 81.1749 +
 81.1750 +    function isStartComment(node) {
 81.1751 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(startCommentRegex);
 81.1752 +    }
 81.1753 +
 81.1754 +    function isEndComment(node) {
 81.1755 +        return (node.nodeType == 8) && (commentNodesHaveTextProperty ? node.text : node.nodeValue).match(endCommentRegex);
 81.1756 +    }
 81.1757 +
 81.1758 +    function getVirtualChildren(startComment, allowUnbalanced) {
 81.1759 +        var currentNode = startComment;
 81.1760 +        var depth = 1;
 81.1761 +        var children = [];
 81.1762 +        while (currentNode = currentNode.nextSibling) {
 81.1763 +            if (isEndComment(currentNode)) {
 81.1764 +                depth--;
 81.1765 +                if (depth === 0)
 81.1766 +                    return children;
 81.1767 +            }
 81.1768 +
 81.1769 +            children.push(currentNode);
 81.1770 +
 81.1771 +            if (isStartComment(currentNode))
 81.1772 +                depth++;
 81.1773 +        }
 81.1774 +        if (!allowUnbalanced)
 81.1775 +            throw new Error("Cannot find closing comment tag to match: " + startComment.nodeValue);
 81.1776 +        return null;
 81.1777 +    }
 81.1778 +
 81.1779 +    function getMatchingEndComment(startComment, allowUnbalanced) {
 81.1780 +        var allVirtualChildren = getVirtualChildren(startComment, allowUnbalanced);
 81.1781 +        if (allVirtualChildren) {
 81.1782 +            if (allVirtualChildren.length > 0)
 81.1783 +                return allVirtualChildren[allVirtualChildren.length - 1].nextSibling;
 81.1784 +            return startComment.nextSibling;
 81.1785 +        } else
 81.1786 +            return null; // Must have no matching end comment, and allowUnbalanced is true
 81.1787 +    }
 81.1788 +
 81.1789 +    function getUnbalancedChildTags(node) {
 81.1790 +        // e.g., from <div>OK</div><!-- ko blah --><span>Another</span>, returns: <!-- ko blah --><span>Another</span>
 81.1791 +        //       from <div>OK</div><!-- /ko --><!-- /ko -->,             returns: <!-- /ko --><!-- /ko -->
 81.1792 +        var childNode = node.firstChild, captureRemaining = null;
 81.1793 +        if (childNode) {
 81.1794 +            do {
 81.1795 +                if (captureRemaining)                   // We already hit an unbalanced node and are now just scooping up all subsequent nodes
 81.1796 +                    captureRemaining.push(childNode);
 81.1797 +                else if (isStartComment(childNode)) {
 81.1798 +                    var matchingEndComment = getMatchingEndComment(childNode, /* allowUnbalanced: */ true);
 81.1799 +                    if (matchingEndComment)             // It's a balanced tag, so skip immediately to the end of this virtual set
 81.1800 +                        childNode = matchingEndComment;
 81.1801 +                    else
 81.1802 +                        captureRemaining = [childNode]; // It's unbalanced, so start capturing from this point
 81.1803 +                } else if (isEndComment(childNode)) {
 81.1804 +                    captureRemaining = [childNode];     // It's unbalanced (if it wasn't, we'd have skipped over it already), so start capturing
 81.1805 +                }
 81.1806 +            } while (childNode = childNode.nextSibling);
 81.1807 +        }
 81.1808 +        return captureRemaining;
 81.1809 +    }
 81.1810 +
 81.1811 +    ko.virtualElements = {
 81.1812 +        allowedBindings: {},
 81.1813 +
 81.1814 +        childNodes: function(node) {
 81.1815 +            return isStartComment(node) ? getVirtualChildren(node) : node.childNodes;
 81.1816 +        },
 81.1817 +
 81.1818 +        emptyNode: function(node) {
 81.1819 +            if (!isStartComment(node))
 81.1820 +                ko.utils.emptyDomNode(node);
 81.1821 +            else {
 81.1822 +                var virtualChildren = ko.virtualElements.childNodes(node);
 81.1823 +                for (var i = 0, j = virtualChildren.length; i < j; i++)
 81.1824 +                    ko.removeNode(virtualChildren[i]);
 81.1825 +            }
 81.1826 +        },
 81.1827 +
 81.1828 +        setDomNodeChildren: function(node, childNodes) {
 81.1829 +            if (!isStartComment(node))
 81.1830 +                ko.utils.setDomNodeChildren(node, childNodes);
 81.1831 +            else {
 81.1832 +                ko.virtualElements.emptyNode(node);
 81.1833 +                var endCommentNode = node.nextSibling; // Must be the next sibling, as we just emptied the children
 81.1834 +                for (var i = 0, j = childNodes.length; i < j; i++)
 81.1835 +                    endCommentNode.parentNode.insertBefore(childNodes[i], endCommentNode);
 81.1836 +            }
 81.1837 +        },
 81.1838 +
 81.1839 +        prepend: function(containerNode, nodeToPrepend) {
 81.1840 +            if (!isStartComment(containerNode)) {
 81.1841 +                if (containerNode.firstChild)
 81.1842 +                    containerNode.insertBefore(nodeToPrepend, containerNode.firstChild);
 81.1843 +                else
 81.1844 +                    containerNode.appendChild(nodeToPrepend);
 81.1845 +            } else {
 81.1846 +                // Start comments must always have a parent and at least one following sibling (the end comment)
 81.1847 +                containerNode.parentNode.insertBefore(nodeToPrepend, containerNode.nextSibling);
 81.1848 +            }
 81.1849 +        },
 81.1850 +
 81.1851 +        insertAfter: function(containerNode, nodeToInsert, insertAfterNode) {
 81.1852 +            if (!insertAfterNode) {
 81.1853 +                ko.virtualElements.prepend(containerNode, nodeToInsert);
 81.1854 +            } else if (!isStartComment(containerNode)) {
 81.1855 +                // Insert after insertion point
 81.1856 +                if (insertAfterNode.nextSibling)
 81.1857 +                    containerNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
 81.1858 +                else
 81.1859 +                    containerNode.appendChild(nodeToInsert);
 81.1860 +            } else {
 81.1861 +                // Children of start comments must always have a parent and at least one following sibling (the end comment)
 81.1862 +                containerNode.parentNode.insertBefore(nodeToInsert, insertAfterNode.nextSibling);
 81.1863 +            }
 81.1864 +        },
 81.1865 +
 81.1866 +        firstChild: function(node) {
 81.1867 +            if (!isStartComment(node))
 81.1868 +                return node.firstChild;
 81.1869 +            if (!node.nextSibling || isEndComment(node.nextSibling))
 81.1870 +                return null;
 81.1871 +            return node.nextSibling;
 81.1872 +        },
 81.1873 +
 81.1874 +        nextSibling: function(node) {
 81.1875 +            if (isStartComment(node))
 81.1876 +                node = getMatchingEndComment(node);
 81.1877 +            if (node.nextSibling && isEndComment(node.nextSibling))
 81.1878 +                return null;
 81.1879 +            return node.nextSibling;
 81.1880 +        },
 81.1881 +
 81.1882 +        virtualNodeBindingValue: function(node) {
 81.1883 +            var regexMatch = isStartComment(node);
 81.1884 +            return regexMatch ? regexMatch[1] : null;
 81.1885 +        },
 81.1886 +
 81.1887 +        normaliseVirtualElementDomStructure: function(elementVerified) {
 81.1888 +            // Workaround for https://github.com/SteveSanderson/knockout/issues/155
 81.1889 +            // (IE <= 8 or IE 9 quirks mode parses your HTML weirdly, treating closing </li> tags as if they don't exist, thereby moving comment nodes
 81.1890 +            // that are direct descendants of <ul> into the preceding <li>)
 81.1891 +            if (!htmlTagsWithOptionallyClosingChildren[ko.utils.tagNameLower(elementVerified)])
 81.1892 +                return;
 81.1893 +
 81.1894 +            // Scan immediate children to see if they contain unbalanced comment tags. If they do, those comment tags
 81.1895 +            // must be intended to appear *after* that child, so move them there.
 81.1896 +            var childNode = elementVerified.firstChild;
 81.1897 +            if (childNode) {
 81.1898 +                do {
 81.1899 +                    if (childNode.nodeType === 1) {
 81.1900 +                        var unbalancedTags = getUnbalancedChildTags(childNode);
 81.1901 +                        if (unbalancedTags) {
 81.1902 +                            // Fix up the DOM by moving the unbalanced tags to where they most likely were intended to be placed - *after* the child
 81.1903 +                            var nodeToInsertBefore = childNode.nextSibling;
 81.1904 +                            for (var i = 0; i < unbalancedTags.length; i++) {
 81.1905 +                                if (nodeToInsertBefore)
 81.1906 +                                    elementVerified.insertBefore(unbalancedTags[i], nodeToInsertBefore);
 81.1907 +                                else
 81.1908 +                                    elementVerified.appendChild(unbalancedTags[i]);
 81.1909 +                            }
 81.1910 +                        }
 81.1911 +                    }
 81.1912 +                } while (childNode = childNode.nextSibling);
 81.1913 +            }
 81.1914 +        }
 81.1915 +    };
 81.1916 +})();
 81.1917 +ko.exportSymbol('virtualElements', ko.virtualElements);
 81.1918 +ko.exportSymbol('virtualElements.allowedBindings', ko.virtualElements.allowedBindings);
 81.1919 +ko.exportSymbol('virtualElements.emptyNode', ko.virtualElements.emptyNode);
 81.1920 +//ko.exportSymbol('virtualElements.firstChild', ko.virtualElements.firstChild);     // firstChild is not minified
 81.1921 +ko.exportSymbol('virtualElements.insertAfter', ko.virtualElements.insertAfter);
 81.1922 +//ko.exportSymbol('virtualElements.nextSibling', ko.virtualElements.nextSibling);   // nextSibling is not minified
 81.1923 +ko.exportSymbol('virtualElements.prepend', ko.virtualElements.prepend);
 81.1924 +ko.exportSymbol('virtualElements.setDomNodeChildren', ko.virtualElements.setDomNodeChildren);
 81.1925 +(function() {
 81.1926 +    var defaultBindingAttributeName = "data-bind";
 81.1927 +
 81.1928 +    ko.bindingProvider = function() {
 81.1929 +        this.bindingCache = {};
 81.1930 +    };
 81.1931 +
 81.1932 +    ko.utils.extend(ko.bindingProvider.prototype, {
 81.1933 +        'nodeHasBindings': function(node) {
 81.1934 +            switch (node.nodeType) {
 81.1935 +                case 1: return node.getAttribute(defaultBindingAttributeName) != null;   // Element
 81.1936 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node) != null; // Comment node
 81.1937 +                default: return false;
 81.1938 +            }
 81.1939 +        },
 81.1940 +
 81.1941 +        'getBindings': function(node, bindingContext) {
 81.1942 +            var bindingsString = this['getBindingsString'](node, bindingContext);
 81.1943 +            return bindingsString ? this['parseBindingsString'](bindingsString, bindingContext, node) : null;
 81.1944 +        },
 81.1945 +
 81.1946 +        // The following function is only used internally by this default provider.
 81.1947 +        // It's not part of the interface definition for a general binding provider.
 81.1948 +        'getBindingsString': function(node, bindingContext) {
 81.1949 +            switch (node.nodeType) {
 81.1950 +                case 1: return node.getAttribute(defaultBindingAttributeName);   // Element
 81.1951 +                case 8: return ko.virtualElements.virtualNodeBindingValue(node); // Comment node
 81.1952 +                default: return null;
 81.1953 +            }
 81.1954 +        },
 81.1955 +
 81.1956 +        // The following function is only used internally by this default provider.
 81.1957 +        // It's not part of the interface definition for a general binding provider.
 81.1958 +        'parseBindingsString': function(bindingsString, bindingContext, node) {
 81.1959 +            try {
 81.1960 +                var bindingFunction = createBindingsStringEvaluatorViaCache(bindingsString, this.bindingCache);
 81.1961 +                return bindingFunction(bindingContext, node);
 81.1962 +            } catch (ex) {
 81.1963 +                throw new Error("Unable to parse bindings.\nMessage: " + ex + ";\nBindings value: " + bindingsString);
 81.1964 +            }
 81.1965 +        }
 81.1966 +    });
 81.1967 +
 81.1968 +    ko.bindingProvider['instance'] = new ko.bindingProvider();
 81.1969 +
 81.1970 +    function createBindingsStringEvaluatorViaCache(bindingsString, cache) {
 81.1971 +        var cacheKey = bindingsString;
 81.1972 +        return cache[cacheKey]
 81.1973 +            || (cache[cacheKey] = createBindingsStringEvaluator(bindingsString));
 81.1974 +    }
 81.1975 +
 81.1976 +    function createBindingsStringEvaluator(bindingsString) {
 81.1977 +        // Build the source for a function that evaluates "expression"
 81.1978 +        // For each scope variable, add an extra level of "with" nesting
 81.1979 +        // Example result: with(sc1) { with(sc0) { return (expression) } }
 81.1980 +        var rewrittenBindings = ko.expressionRewriting.preProcessBindings(bindingsString),
 81.1981 +            functionBody = "with($context){with($data||{}){return{" + rewrittenBindings + "}}}";
 81.1982 +        return new Function("$context", "$element", functionBody);
 81.1983 +    }
 81.1984 +})();
 81.1985 +
 81.1986 +ko.exportSymbol('bindingProvider', ko.bindingProvider);
 81.1987 +(function () {
 81.1988 +    ko.bindingHandlers = {};
 81.1989 +
 81.1990 +    ko.bindingContext = function(dataItem, parentBindingContext, dataItemAlias) {
 81.1991 +        if (parentBindingContext) {
 81.1992 +            ko.utils.extend(this, parentBindingContext); // Inherit $root and any custom properties
 81.1993 +            this['$parentContext'] = parentBindingContext;
 81.1994 +            this['$parent'] = parentBindingContext['$data'];
 81.1995 +            this['$parents'] = (parentBindingContext['$parents'] || []).slice(0);
 81.1996 +            this['$parents'].unshift(this['$parent']);
 81.1997 +        } else {
 81.1998 +            this['$parents'] = [];
 81.1999 +            this['$root'] = dataItem;
 81.2000 +            // Export 'ko' in the binding context so it will be available in bindings and templates
 81.2001 +            // even if 'ko' isn't exported as a global, such as when using an AMD loader.
 81.2002 +            // See https://github.com/SteveSanderson/knockout/issues/490
 81.2003 +            this['ko'] = ko;
 81.2004 +        }
 81.2005 +        this['$data'] = dataItem;
 81.2006 +        if (dataItemAlias)
 81.2007 +            this[dataItemAlias] = dataItem;
 81.2008 +    }
 81.2009 +    ko.bindingContext.prototype['createChildContext'] = function (dataItem, dataItemAlias) {
 81.2010 +        return new ko.bindingContext(dataItem, this, dataItemAlias);
 81.2011 +    };
 81.2012 +    ko.bindingContext.prototype['extend'] = function(properties) {
 81.2013 +        var clone = ko.utils.extend(new ko.bindingContext(), this);
 81.2014 +        return ko.utils.extend(clone, properties);
 81.2015 +    };
 81.2016 +
 81.2017 +    function validateThatBindingIsAllowedForVirtualElements(bindingName) {
 81.2018 +        var validator = ko.virtualElements.allowedBindings[bindingName];
 81.2019 +        if (!validator)
 81.2020 +            throw new Error("The binding '" + bindingName + "' cannot be used with virtual elements")
 81.2021 +    }
 81.2022 +
 81.2023 +    function applyBindingsToDescendantsInternal (viewModel, elementOrVirtualElement, bindingContextsMayDifferFromDomParentElement) {
 81.2024 +        var currentChild, nextInQueue = ko.virtualElements.firstChild(elementOrVirtualElement);
 81.2025 +        while (currentChild = nextInQueue) {
 81.2026 +            // Keep a record of the next child *before* applying bindings, in case the binding removes the current child from its position
 81.2027 +            nextInQueue = ko.virtualElements.nextSibling(currentChild);
 81.2028 +            applyBindingsToNodeAndDescendantsInternal(viewModel, currentChild, bindingContextsMayDifferFromDomParentElement);
 81.2029 +        }
 81.2030 +    }
 81.2031 +
 81.2032 +    function applyBindingsToNodeAndDescendantsInternal (viewModel, nodeVerified, bindingContextMayDifferFromDomParentElement) {
 81.2033 +        var shouldBindDescendants = true;
 81.2034 +
 81.2035 +        // Perf optimisation: Apply bindings only if...
 81.2036 +        // (1) We need to store the binding context on this node (because it may differ from the DOM parent node's binding context)
 81.2037 +        //     Note that we can't store binding contexts on non-elements (e.g., text nodes), as IE doesn't allow expando properties for those
 81.2038 +        // (2) It might have bindings (e.g., it has a data-bind attribute, or it's a marker for a containerless template)
 81.2039 +        var isElement = (nodeVerified.nodeType === 1);
 81.2040 +        if (isElement) // Workaround IE <= 8 HTML parsing weirdness
 81.2041 +            ko.virtualElements.normaliseVirtualElementDomStructure(nodeVerified);
 81.2042 +
 81.2043 +        var shouldApplyBindings = (isElement && bindingContextMayDifferFromDomParentElement)             // Case (1)
 81.2044 +                               || ko.bindingProvider['instance']['nodeHasBindings'](nodeVerified);       // Case (2)
 81.2045 +        if (shouldApplyBindings)
 81.2046 +            shouldBindDescendants = applyBindingsToNodeInternal(nodeVerified, null, viewModel, bindingContextMayDifferFromDomParentElement).shouldBindDescendants;
 81.2047 +
 81.2048 +        if (shouldBindDescendants) {
 81.2049 +            // We're recursing automatically into (real or virtual) child nodes without changing binding contexts. So,
 81.2050 +            //  * For children of a *real* element, the binding context is certainly the same as on their DOM .parentNode,
 81.2051 +            //    hence bindingContextsMayDifferFromDomParentElement is false
 81.2052 +            //  * For children of a *virtual* element, we can't be sure. Evaluating .parentNode on those children may
 81.2053 +            //    skip over any number of intermediate virtual elements, any of which might define a custom binding context,
 81.2054 +            //    hence bindingContextsMayDifferFromDomParentElement is true
 81.2055 +            applyBindingsToDescendantsInternal(viewModel, nodeVerified, /* bindingContextsMayDifferFromDomParentElement: */ !isElement);
 81.2056 +        }
 81.2057 +    }
 81.2058 +
 81.2059 +    function applyBindingsToNodeInternal (node, bindings, viewModelOrBindingContext, bindingContextMayDifferFromDomParentElement) {
 81.2060 +        // Need to be sure that inits are only run once, and updates never run until all the inits have been run
 81.2061 +        var initPhase = 0; // 0 = before all inits, 1 = during inits, 2 = after all inits
 81.2062 +
 81.2063 +        // Each time the dependentObservable is evaluated (after data changes),
 81.2064 +        // the binding attribute is reparsed so that it can pick out the correct
 81.2065 +        // model properties in the context of the changed data.
 81.2066 +        // DOM event callbacks need to be able to access this changed data,
 81.2067 +        // so we need a single parsedBindings variable (shared by all callbacks
 81.2068 +        // associated with this node's bindings) that all the closures can access.
 81.2069 +        var parsedBindings;
 81.2070 +        function makeValueAccessor(bindingKey) {
 81.2071 +            return function () { return parsedBindings[bindingKey] }
 81.2072 +        }
 81.2073 +        function parsedBindingsAccessor() {
 81.2074 +            return parsedBindings;
 81.2075 +        }
 81.2076 +
 81.2077 +        var bindingHandlerThatControlsDescendantBindings;
 81.2078 +        ko.dependentObservable(
 81.2079 +            function () {
 81.2080 +                // Ensure we have a nonnull binding context to work with
 81.2081 +                var bindingContextInstance = viewModelOrBindingContext && (viewModelOrBindingContext instanceof ko.bindingContext)
 81.2082 +                    ? viewModelOrBindingContext
 81.2083 +                    : new ko.bindingContext(ko.utils.unwrapObservable(viewModelOrBindingContext));
 81.2084 +                var viewModel = bindingContextInstance['$data'];
 81.2085 +
 81.2086 +                // Optimization: Don't store the binding context on this node if it's definitely the same as on node.parentNode, because
 81.2087 +                // we can easily recover it just by scanning up the node's ancestors in the DOM
 81.2088 +                // (note: here, parent node means "real DOM parent" not "virtual parent", as there's no O(1) way to find the virtual parent)
 81.2089 +                if (bindingContextMayDifferFromDomParentElement)
 81.2090 +                    ko.storedBindingContextForNode(node, bindingContextInstance);
 81.2091 +
 81.2092 +                // Use evaluatedBindings if given, otherwise fall back on asking the bindings provider to give us some bindings
 81.2093 +                var evaluatedBindings = (typeof bindings == "function") ? bindings(bindingContextInstance, node) : bindings;
 81.2094 +                parsedBindings = evaluatedBindings || ko.bindingProvider['instance']['getBindings'](node, bindingContextInstance);
 81.2095 +
 81.2096 +                if (parsedBindings) {
 81.2097 +                    // First run all the inits, so bindings can register for notification on changes
 81.2098 +                    if (initPhase === 0) {
 81.2099 +                        initPhase = 1;
 81.2100 +                        for (var bindingKey in parsedBindings) {
 81.2101 +                            var binding = ko.bindingHandlers[bindingKey];
 81.2102 +                            if (binding && node.nodeType === 8)
 81.2103 +                                validateThatBindingIsAllowedForVirtualElements(bindingKey);
 81.2104 +
 81.2105 +                            if (binding && typeof binding["init"] == "function") {
 81.2106 +                                var handlerInitFn = binding["init"];
 81.2107 +                                var initResult = handlerInitFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
 81.2108 +
 81.2109 +                                // If this binding handler claims to control descendant bindings, make a note of this
 81.2110 +                                if (initResult && initResult['controlsDescendantBindings']) {
 81.2111 +                                    if (bindingHandlerThatControlsDescendantBindings !== undefined)
 81.2112 +                                        throw new Error("Multiple bindings (" + bindingHandlerThatControlsDescendantBindings + " and " + bindingKey + ") are trying to control descendant bindings of the same element. You cannot use these bindings together on the same element.");
 81.2113 +                                    bindingHandlerThatControlsDescendantBindings = bindingKey;
 81.2114 +                                }
 81.2115 +                            }
 81.2116 +                        }
 81.2117 +                        initPhase = 2;
 81.2118 +                    }
 81.2119 +
 81.2120 +                    // ... then run all the updates, which might trigger changes even on the first evaluation
 81.2121 +                    if (initPhase === 2) {
 81.2122 +                        for (var bindingKey in parsedBindings) {
 81.2123 +                            var binding = ko.bindingHandlers[bindingKey];
 81.2124 +                            if (binding && typeof binding["update"] == "function") {
 81.2125 +                                var handlerUpdateFn = binding["update"];
 81.2126 +                                handlerUpdateFn(node, makeValueAccessor(bindingKey), parsedBindingsAccessor, viewModel, bindingContextInstance);
 81.2127 +                            }
 81.2128 +                        }
 81.2129 +                    }
 81.2130 +                }
 81.2131 +            },
 81.2132 +            null,
 81.2133 +            { disposeWhenNodeIsRemoved : node }
 81.2134 +        );
 81.2135 +
 81.2136 +        return {
 81.2137 +            shouldBindDescendants: bindingHandlerThatControlsDescendantBindings === undefined
 81.2138 +        };
 81.2139 +    };
 81.2140 +
 81.2141 +    var storedBindingContextDomDataKey = "__ko_bindingContext__";
 81.2142 +    ko.storedBindingContextForNode = function (node, bindingContext) {
 81.2143 +        if (arguments.length == 2)
 81.2144 +            ko.utils.domData.set(node, storedBindingContextDomDataKey, bindingContext);
 81.2145 +        else
 81.2146 +            return ko.utils.domData.get(node, storedBindingContextDomDataKey);
 81.2147 +    }
 81.2148 +
 81.2149 +    ko.applyBindingsToNode = function (node, bindings, viewModel) {
 81.2150 +        if (node.nodeType === 1) // If it's an element, workaround IE <= 8 HTML parsing weirdness
 81.2151 +            ko.virtualElements.normaliseVirtualElementDomStructure(node);
 81.2152 +        return applyBindingsToNodeInternal(node, bindings, viewModel, true);
 81.2153 +    };
 81.2154 +
 81.2155 +    ko.applyBindingsToDescendants = function(viewModel, rootNode) {
 81.2156 +        if (rootNode.nodeType === 1 || rootNode.nodeType === 8)
 81.2157 +            applyBindingsToDescendantsInternal(viewModel, rootNode, true);
 81.2158 +    };
 81.2159 +
 81.2160 +    ko.applyBindings = function (viewModel, rootNode) {
 81.2161 +        if (rootNode && (rootNode.nodeType !== 1) && (rootNode.nodeType !== 8))
 81.2162 +            throw new Error("ko.applyBindings: first parameter should be your view model; second parameter should be a DOM node");
 81.2163 +        rootNode = rootNode || window.document.body; // Make "rootNode" parameter optional
 81.2164 +
 81.2165 +        applyBindingsToNodeAndDescendantsInternal(viewModel, rootNode, true);
 81.2166 +    };
 81.2167 +
 81.2168 +    // Retrieving binding context from arbitrary nodes
 81.2169 +    ko.contextFor = function(node) {
 81.2170 +        // We can only do something meaningful for elements and comment nodes (in particular, not text nodes, as IE can't store domdata for them)
 81.2171 +        switch (node.nodeType) {
 81.2172 +            case 1:
 81.2173 +            case 8:
 81.2174 +                var context = ko.storedBindingContextForNode(node);
 81.2175 +                if (context) return context;
 81.2176 +                if (node.parentNode) return ko.contextFor(node.parentNode);
 81.2177 +                break;
 81.2178 +        }
 81.2179 +        return undefined;
 81.2180 +    };
 81.2181 +    ko.dataFor = function(node) {
 81.2182 +        var context = ko.contextFor(node);
 81.2183 +        return context ? context['$data'] : undefined;
 81.2184 +    };
 81.2185 +
 81.2186 +    ko.exportSymbol('bindingHandlers', ko.bindingHandlers);
 81.2187 +    ko.exportSymbol('applyBindings', ko.applyBindings);
 81.2188 +    ko.exportSymbol('applyBindingsToDescendants', ko.applyBindingsToDescendants);
 81.2189 +    ko.exportSymbol('applyBindingsToNode', ko.applyBindingsToNode);
 81.2190 +    ko.exportSymbol('contextFor', ko.contextFor);
 81.2191 +    ko.exportSymbol('dataFor', ko.dataFor);
 81.2192 +})();
 81.2193 +var attrHtmlToJavascriptMap = { 'class': 'className', 'for': 'htmlFor' };
 81.2194 +ko.bindingHandlers['attr'] = {
 81.2195 +    'update': function(element, valueAccessor, allBindingsAccessor) {
 81.2196 +        var value = ko.utils.unwrapObservable(valueAccessor()) || {};
 81.2197 +        for (var attrName in value) {
 81.2198 +            if (typeof attrName == "string") {
 81.2199 +                var attrValue = ko.utils.unwrapObservable(value[attrName]);
 81.2200 +
 81.2201 +                // To cover cases like "attr: { checked:someProp }", we want to remove the attribute entirely
 81.2202 +                // when someProp is a "no value"-like value (strictly null, false, or undefined)
 81.2203 +                // (because the absence of the "checked" attr is how to mark an element as not checked, etc.)
 81.2204 +                var toRemove = (attrValue === false) || (attrValue === null) || (attrValue === undefined);
 81.2205 +                if (toRemove)
 81.2206 +                    element.removeAttribute(attrName);
 81.2207 +
 81.2208 +                // In IE <= 7 and IE8 Quirks Mode, you have to use the Javascript property name instead of the
 81.2209 +                // HTML attribute name for certain attributes. IE8 Standards Mode supports the correct behavior,
 81.2210 +                // but instead of figuring out the mode, we'll just set the attribute through the Javascript
 81.2211 +                // property for IE <= 8.
 81.2212 +                if (ko.utils.ieVersion <= 8 && attrName in attrHtmlToJavascriptMap) {
 81.2213 +                    attrName = attrHtmlToJavascriptMap[attrName];
 81.2214 +                    if (toRemove)
 81.2215 +                        element.removeAttribute(attrName);
 81.2216 +                    else
 81.2217 +                        element[attrName] = attrValue;
 81.2218 +                } else if (!toRemove) {
 81.2219 +                    try {
 81.2220 +                        element.setAttribute(attrName, attrValue.toString());
 81.2221 +                    } catch (err) {
 81.2222 +                        // ignore for now
 81.2223 +                        if (console) {
 81.2224 +                            console.log("Can't set attribute " + attrName + " to " + attrValue + " error: " + err);
 81.2225 +                        }
 81.2226 +                    }
 81.2227 +                }
 81.2228 +
 81.2229 +                // Treat "name" specially - although you can think of it as an attribute, it also needs
 81.2230 +                // special handling on older versions of IE (https://github.com/SteveSanderson/knockout/pull/333)
 81.2231 +                // Deliberately being case-sensitive here because XHTML would regard "Name" as a different thing
 81.2232 +                // entirely, and there's no strong reason to allow for such casing in HTML.
 81.2233 +                if (attrName === "name") {
 81.2234 +                    ko.utils.setElementName(element, toRemove ? "" : attrValue.toString());
 81.2235 +                }
 81.2236 +            }
 81.2237 +        }
 81.2238 +    }
 81.2239 +};
 81.2240 +ko.bindingHandlers['checked'] = {
 81.2241 +    'init': function (element, valueAccessor, allBindingsAccessor) {
 81.2242 +        var updateHandler = function() {
 81.2243 +            var valueToWrite;
 81.2244 +            if (element.type == "checkbox") {
 81.2245 +                valueToWrite = element.checked;
 81.2246 +            } else if ((element.type == "radio") && (element.checked)) {
 81.2247 +                valueToWrite = element.value;
 81.2248 +            } else {
 81.2249 +                return; // "checked" binding only responds to checkboxes and selected radio buttons
 81.2250 +            }
 81.2251 +
 81.2252 +            var modelValue = valueAccessor(), unwrappedValue = ko.utils.unwrapObservable(modelValue);
 81.2253 +            if ((element.type == "checkbox") && (unwrappedValue instanceof Array)) {
 81.2254 +                // For checkboxes bound to an array, we add/remove the checkbox value to that array
 81.2255 +                // This works for both observable and non-observable arrays
 81.2256 +                var existingEntryIndex = ko.utils.arrayIndexOf(unwrappedValue, element.value);
 81.2257 +                if (element.checked && (existingEntryIndex < 0))
 81.2258 +                    modelValue.push(element.value);
 81.2259 +                else if ((!element.checked) && (existingEntryIndex >= 0))
 81.2260 +                    modelValue.splice(existingEntryIndex, 1);
 81.2261 +            } else {
 81.2262 +                ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'checked', valueToWrite, true);
 81.2263 +            }
 81.2264 +        };
 81.2265 +        ko.utils.registerEventHandler(element, "click", updateHandler);
 81.2266 +
 81.2267 +        // IE 6 won't allow radio buttons to be selected unless they have a name
 81.2268 +        if ((element.type == "radio") && !element.name)
 81.2269 +            ko.bindingHandlers['uniqueName']['init'](element, function() { return true });
 81.2270 +    },
 81.2271 +    'update': function (element, valueAccessor) {
 81.2272 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2273 +
 81.2274 +        if (element.type == "checkbox") {
 81.2275 +            if (value instanceof Array) {
 81.2276 +                // When bound to an array, the checkbox being checked represents its value being present in that array
 81.2277 +                element.checked = ko.utils.arrayIndexOf(value, element.value) >= 0;
 81.2278 +            } else {
 81.2279 +                // When bound to anything other value (not an array), the checkbox being checked represents the value being trueish
 81.2280 +                element.checked = value;
 81.2281 +            }
 81.2282 +        } else if (element.type == "radio") {
 81.2283 +            element.checked = (element.value == value);
 81.2284 +        }
 81.2285 +    }
 81.2286 +};
 81.2287 +var classesWrittenByBindingKey = '__ko__cssValue';
 81.2288 +ko.bindingHandlers['css'] = {
 81.2289 +    'update': function (element, valueAccessor) {
 81.2290 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2291 +        if (typeof value == "object") {
 81.2292 +            for (var className in value) {
 81.2293 +                var shouldHaveClass = ko.utils.unwrapObservable(value[className]);
 81.2294 +                ko.utils.toggleDomNodeCssClass(element, className, shouldHaveClass);
 81.2295 +            }
 81.2296 +        } else {
 81.2297 +            value = String(value || ''); // Make sure we don't try to store or set a non-string value
 81.2298 +            ko.utils.toggleDomNodeCssClass(element, element[classesWrittenByBindingKey], false);
 81.2299 +            element[classesWrittenByBindingKey] = value;
 81.2300 +            ko.utils.toggleDomNodeCssClass(element, value, true);
 81.2301 +        }
 81.2302 +    }
 81.2303 +};
 81.2304 +ko.bindingHandlers['enable'] = {
 81.2305 +    'update': function (element, valueAccessor) {
 81.2306 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2307 +        if (value && element.disabled)
 81.2308 +            element.removeAttribute("disabled");
 81.2309 +        else if ((!value) && (!element.disabled))
 81.2310 +            element.disabled = true;
 81.2311 +    }
 81.2312 +};
 81.2313 +
 81.2314 +ko.bindingHandlers['disable'] = {
 81.2315 +    'update': function (element, valueAccessor) {
 81.2316 +        ko.bindingHandlers['enable']['update'](element, function() { return !ko.utils.unwrapObservable(valueAccessor()) });
 81.2317 +    }
 81.2318 +};
 81.2319 +// For certain common events (currently just 'click'), allow a simplified data-binding syntax
 81.2320 +// e.g. click:handler instead of the usual full-length event:{click:handler}
 81.2321 +function makeEventHandlerShortcut(eventName) {
 81.2322 +    ko.bindingHandlers[eventName] = {
 81.2323 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel) {
 81.2324 +            var newValueAccessor = function () {
 81.2325 +                var result = {};
 81.2326 +                result[eventName] = valueAccessor();
 81.2327 +                return result;
 81.2328 +            };
 81.2329 +            return ko.bindingHandlers['event']['init'].call(this, element, newValueAccessor, allBindingsAccessor, viewModel);
 81.2330 +        }
 81.2331 +    }
 81.2332 +}
 81.2333 +
 81.2334 +ko.bindingHandlers['event'] = {
 81.2335 +    'init' : function (element, valueAccessor, allBindingsAccessor, viewModel) {
 81.2336 +        var eventsToHandle = valueAccessor() || {};
 81.2337 +        for(var eventNameOutsideClosure in eventsToHandle) {
 81.2338 +            (function() {
 81.2339 +                var eventName = eventNameOutsideClosure; // Separate variable to be captured by event handler closure
 81.2340 +                if (typeof eventName == "string") {
 81.2341 +                    ko.utils.registerEventHandler(element, eventName, function (event) {
 81.2342 +                        var handlerReturnValue;
 81.2343 +                        var handlerFunction = valueAccessor()[eventName];
 81.2344 +                        if (!handlerFunction)
 81.2345 +                            return;
 81.2346 +                        var allBindings = allBindingsAccessor();
 81.2347 +
 81.2348 +                        try {
 81.2349 +                            // Take all the event args, and prefix with the viewmodel
 81.2350 +                            var argsForHandler = ko.utils.makeArray(arguments);
 81.2351 +                            argsForHandler.unshift(viewModel);
 81.2352 +                            handlerReturnValue = handlerFunction.apply(viewModel, argsForHandler);
 81.2353 +                        } finally {
 81.2354 +                            if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
 81.2355 +                                if (event.preventDefault)
 81.2356 +                                    event.preventDefault();
 81.2357 +                                else
 81.2358 +                                    event.returnValue = false;
 81.2359 +                            }
 81.2360 +                        }
 81.2361 +
 81.2362 +                        var bubble = allBindings[eventName + 'Bubble'] !== false;
 81.2363 +                        if (!bubble) {
 81.2364 +                            event.cancelBubble = true;
 81.2365 +                            if (event.stopPropagation)
 81.2366 +                                event.stopPropagation();
 81.2367 +                        }
 81.2368 +                    });
 81.2369 +                }
 81.2370 +            })();
 81.2371 +        }
 81.2372 +    }
 81.2373 +};
 81.2374 +// "foreach: someExpression" is equivalent to "template: { foreach: someExpression }"
 81.2375 +// "foreach: { data: someExpression, afterAdd: myfn }" is equivalent to "template: { foreach: someExpression, afterAdd: myfn }"
 81.2376 +ko.bindingHandlers['foreach'] = {
 81.2377 +    makeTemplateValueAccessor: function(valueAccessor) {
 81.2378 +        return function() {
 81.2379 +            var modelValue = valueAccessor(),
 81.2380 +                unwrappedValue = ko.utils.peekObservable(modelValue);    // Unwrap without setting a dependency here
 81.2381 +
 81.2382 +            // If unwrappedValue is the array, pass in the wrapped value on its own
 81.2383 +            // The value will be unwrapped and tracked within the template binding
 81.2384 +            // (See https://github.com/SteveSanderson/knockout/issues/523)
 81.2385 +            if ((!unwrappedValue) || typeof unwrappedValue.length == "number")
 81.2386 +                return { 'foreach': modelValue, 'templateEngine': ko.nativeTemplateEngine.instance };
 81.2387 +
 81.2388 +            // If unwrappedValue.data is the array, preserve all relevant options and unwrap again value so we get updates
 81.2389 +            ko.utils.unwrapObservable(modelValue);
 81.2390 +            return {
 81.2391 +                'foreach': unwrappedValue['data'],
 81.2392 +                'as': unwrappedValue['as'],
 81.2393 +                'includeDestroyed': unwrappedValue['includeDestroyed'],
 81.2394 +                'afterAdd': unwrappedValue['afterAdd'],
 81.2395 +                'beforeRemove': unwrappedValue['beforeRemove'],
 81.2396 +                'afterRender': unwrappedValue['afterRender'],
 81.2397 +                'beforeMove': unwrappedValue['beforeMove'],
 81.2398 +                'afterMove': unwrappedValue['afterMove'],
 81.2399 +                'templateEngine': ko.nativeTemplateEngine.instance
 81.2400 +            };
 81.2401 +        };
 81.2402 +    },
 81.2403 +    'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
 81.2404 +        return ko.bindingHandlers['template']['init'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor));
 81.2405 +    },
 81.2406 +    'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
 81.2407 +        return ko.bindingHandlers['template']['update'](element, ko.bindingHandlers['foreach'].makeTemplateValueAccessor(valueAccessor), allBindingsAccessor, viewModel, bindingContext);
 81.2408 +    }
 81.2409 +};
 81.2410 +ko.expressionRewriting.bindingRewriteValidators['foreach'] = false; // Can't rewrite control flow bindings
 81.2411 +ko.virtualElements.allowedBindings['foreach'] = true;
 81.2412 +var hasfocusUpdatingProperty = '__ko_hasfocusUpdating';
 81.2413 +ko.bindingHandlers['hasfocus'] = {
 81.2414 +    'init': function(element, valueAccessor, allBindingsAccessor) {
 81.2415 +        var handleElementFocusChange = function(isFocused) {
 81.2416 +            // Where possible, ignore which event was raised and determine focus state using activeElement,
 81.2417 +            // as this avoids phantom focus/blur events raised when changing tabs in modern browsers.
 81.2418 +            // However, not all KO-targeted browsers (Firefox 2) support activeElement. For those browsers,
 81.2419 +            // prevent a loss of focus when changing tabs/windows by setting a flag that prevents hasfocus
 81.2420 +            // from calling 'blur()' on the element when it loses focus.
 81.2421 +            // Discussion at https://github.com/SteveSanderson/knockout/pull/352
 81.2422 +            element[hasfocusUpdatingProperty] = true;
 81.2423 +            var ownerDoc = element.ownerDocument;
 81.2424 +            if ("activeElement" in ownerDoc) {
 81.2425 +                isFocused = (ownerDoc.activeElement === element);
 81.2426 +            }
 81.2427 +            var modelValue = valueAccessor();
 81.2428 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'hasfocus', isFocused, true);
 81.2429 +            element[hasfocusUpdatingProperty] = false;
 81.2430 +        };
 81.2431 +        var handleElementFocusIn = handleElementFocusChange.bind(null, true);
 81.2432 +        var handleElementFocusOut = handleElementFocusChange.bind(null, false);
 81.2433 +
 81.2434 +        ko.utils.registerEventHandler(element, "focus", handleElementFocusIn);
 81.2435 +        ko.utils.registerEventHandler(element, "focusin", handleElementFocusIn); // For IE
 81.2436 +        ko.utils.registerEventHandler(element, "blur",  handleElementFocusOut);
 81.2437 +        ko.utils.registerEventHandler(element, "focusout",  handleElementFocusOut); // For IE
 81.2438 +    },
 81.2439 +    'update': function(element, valueAccessor) {
 81.2440 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2441 +        if (!element[hasfocusUpdatingProperty]) {
 81.2442 +            value ? element.focus() : element.blur();
 81.2443 +            ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, value ? "focusin" : "focusout"]); // For IE, which doesn't reliably fire "focus" or "blur" events synchronously
 81.2444 +        }
 81.2445 +    }
 81.2446 +};
 81.2447 +ko.bindingHandlers['html'] = {
 81.2448 +    'init': function() {
 81.2449 +        // Prevent binding on the dynamically-injected HTML (as developers are unlikely to expect that, and it has security implications)
 81.2450 +        return { 'controlsDescendantBindings': true };
 81.2451 +    },
 81.2452 +    'update': function (element, valueAccessor) {
 81.2453 +        // setHtml will unwrap the value if needed
 81.2454 +        ko.utils.setHtml(element, valueAccessor());
 81.2455 +    }
 81.2456 +};
 81.2457 +var withIfDomDataKey = '__ko_withIfBindingData';
 81.2458 +// Makes a binding like with or if
 81.2459 +function makeWithIfBinding(bindingKey, isWith, isNot, makeContextCallback) {
 81.2460 +    ko.bindingHandlers[bindingKey] = {
 81.2461 +        'init': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
 81.2462 +            ko.utils.domData.set(element, withIfDomDataKey, {});
 81.2463 +            return { 'controlsDescendantBindings': true };
 81.2464 +        },
 81.2465 +        'update': function(element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
 81.2466 +            var withIfData = ko.utils.domData.get(element, withIfDomDataKey),
 81.2467 +                dataValue = ko.utils.unwrapObservable(valueAccessor()),
 81.2468 +                shouldDisplay = !isNot !== !dataValue, // equivalent to isNot ? !dataValue : !!dataValue
 81.2469 +                isFirstRender = !withIfData.savedNodes,
 81.2470 +                needsRefresh = isFirstRender || isWith || (shouldDisplay !== withIfData.didDisplayOnLastUpdate);
 81.2471 +
 81.2472 +            if (needsRefresh) {
 81.2473 +                if (isFirstRender) {
 81.2474 +                    withIfData.savedNodes = ko.utils.cloneNodes(ko.virtualElements.childNodes(element), true /* shouldCleanNodes */);
 81.2475 +                }
 81.2476 +
 81.2477 +                if (shouldDisplay) {
 81.2478 +                    if (!isFirstRender) {
 81.2479 +                        ko.virtualElements.setDomNodeChildren(element, ko.utils.cloneNodes(withIfData.savedNodes));
 81.2480 +                    }
 81.2481 +                    ko.applyBindingsToDescendants(makeContextCallback ? makeContextCallback(bindingContext, dataValue) : bindingContext, element);
 81.2482 +                } else {
 81.2483 +                    ko.virtualElements.emptyNode(element);
 81.2484 +                }
 81.2485 +
 81.2486 +                withIfData.didDisplayOnLastUpdate = shouldDisplay;
 81.2487 +            }
 81.2488 +        }
 81.2489 +    };
 81.2490 +    ko.expressionRewriting.bindingRewriteValidators[bindingKey] = false; // Can't rewrite control flow bindings
 81.2491 +    ko.virtualElements.allowedBindings[bindingKey] = true;
 81.2492 +}
 81.2493 +
 81.2494 +// Construct the actual binding handlers
 81.2495 +makeWithIfBinding('if');
 81.2496 +makeWithIfBinding('ifnot', false /* isWith */, true /* isNot */);
 81.2497 +makeWithIfBinding('with', true /* isWith */, false /* isNot */,
 81.2498 +    function(bindingContext, dataValue) {
 81.2499 +        return bindingContext['createChildContext'](dataValue);
 81.2500 +    }
 81.2501 +);
 81.2502 +function ensureDropdownSelectionIsConsistentWithModelValue(element, modelValue, preferModelValue) {
 81.2503 +    if (preferModelValue) {
 81.2504 +        if (modelValue !== ko.selectExtensions.readValue(element))
 81.2505 +            ko.selectExtensions.writeValue(element, modelValue);
 81.2506 +    }
 81.2507 +
 81.2508 +    // No matter which direction we're syncing in, we want the end result to be equality between dropdown value and model value.
 81.2509 +    // If they aren't equal, either we prefer the dropdown value, or the model value couldn't be represented, so either way,
 81.2510 +    // change the model value to match the dropdown.
 81.2511 +    if (modelValue !== ko.selectExtensions.readValue(element))
 81.2512 +        ko.dependencyDetection.ignore(ko.utils.triggerEvent, null, [element, "change"]);
 81.2513 +};
 81.2514 +
 81.2515 +ko.bindingHandlers['options'] = {
 81.2516 +    'update': function (element, valueAccessor, allBindingsAccessor) {
 81.2517 +        if (ko.utils.tagNameLower(element) !== "select")
 81.2518 +            throw new Error("options binding applies only to SELECT elements");
 81.2519 +
 81.2520 +        var selectWasPreviouslyEmpty = element.length == 0;
 81.2521 +        var previousSelectedValues = ko.utils.arrayMap(ko.utils.arrayFilter(element.childNodes, function (node) {
 81.2522 +            return node.tagName && (ko.utils.tagNameLower(node) === "option") && node.selected;
 81.2523 +        }), function (node) {
 81.2524 +            return ko.selectExtensions.readValue(node) || node.innerText || node.textContent;
 81.2525 +        });
 81.2526 +        var previousScrollTop = element.scrollTop;
 81.2527 +
 81.2528 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2529 +        var selectedValue = element.value;
 81.2530 +
 81.2531 +        // Remove all existing <option>s.
 81.2532 +        // Need to use .remove() rather than .removeChild() for <option>s otherwise IE behaves oddly (https://github.com/SteveSanderson/knockout/issues/134)
 81.2533 +        while (element.length > 0) {
 81.2534 +            ko.cleanNode(element.options[0]);
 81.2535 +            element.remove(0);
 81.2536 +        }
 81.2537 +
 81.2538 +        if (value) {
 81.2539 +            var allBindings = allBindingsAccessor(),
 81.2540 +                includeDestroyed = allBindings['optionsIncludeDestroyed'];
 81.2541 +
 81.2542 +            if (typeof value.length != "number")
 81.2543 +                value = [value];
 81.2544 +            if (allBindings['optionsCaption']) {
 81.2545 +                var option = document.createElement("option");
 81.2546 +                ko.utils.setHtml(option, allBindings['optionsCaption']);
 81.2547 +                ko.selectExtensions.writeValue(option, undefined);
 81.2548 +                element.appendChild(option);
 81.2549 +            }
 81.2550 +
 81.2551 +            for (var i = 0, j = value.length; i < j; i++) {
 81.2552 +                // Skip destroyed items
 81.2553 +                var arrayEntry = value[i];
 81.2554 +                if (arrayEntry && arrayEntry['_destroy'] && !includeDestroyed)
 81.2555 +                    continue;
 81.2556 +
 81.2557 +                var option = document.createElement("option");
 81.2558 +
 81.2559 +                function applyToObject(object, predicate, defaultValue) {
 81.2560 +                    var predicateType = typeof predicate;
 81.2561 +                    if (predicateType == "function")    // Given a function; run it against the data value
 81.2562 +                        return predicate(object);
 81.2563 +                    else if (predicateType == "string") // Given a string; treat it as a property name on the data value
 81.2564 +                        return object[predicate];
 81.2565 +                    else                                // Given no optionsText arg; use the data value itself
 81.2566 +                        return defaultValue;
 81.2567 +                }
 81.2568 +
 81.2569 +                // Apply a value to the option element
 81.2570 +                var optionValue = applyToObject(arrayEntry, allBindings['optionsValue'], arrayEntry);
 81.2571 +                ko.selectExtensions.writeValue(option, ko.utils.unwrapObservable(optionValue));
 81.2572 +
 81.2573 +                // Apply some text to the option element
 81.2574 +                var optionText = applyToObject(arrayEntry, allBindings['optionsText'], optionValue);
 81.2575 +                ko.utils.setTextContent(option, optionText);
 81.2576 +
 81.2577 +                element.appendChild(option);
 81.2578 +            }
 81.2579 +
 81.2580 +            // IE6 doesn't like us to assign selection to OPTION nodes before they're added to the document.
 81.2581 +            // That's why we first added them without selection. Now it's time to set the selection.
 81.2582 +            var newOptions = element.getElementsByTagName("option");
 81.2583 +            var countSelectionsRetained = 0;
 81.2584 +            for (var i = 0, j = newOptions.length; i < j; i++) {
 81.2585 +                if (ko.utils.arrayIndexOf(previousSelectedValues, ko.selectExtensions.readValue(newOptions[i])) >= 0) {
 81.2586 +                    ko.utils.setOptionNodeSelectionState(newOptions[i], true);
 81.2587 +                    countSelectionsRetained++;
 81.2588 +                }
 81.2589 +            }
 81.2590 +
 81.2591 +            element.scrollTop = previousScrollTop;
 81.2592 +
 81.2593 +            if (selectWasPreviouslyEmpty && ('value' in allBindings)) {
 81.2594 +                // Ensure consistency between model value and selected option.
 81.2595 +                // If the dropdown is being populated for the first time here (or was otherwise previously empty),
 81.2596 +                // the dropdown selection state is meaningless, so we preserve the model value.
 81.2597 +                ensureDropdownSelectionIsConsistentWithModelValue(element, ko.utils.peekObservable(allBindings['value']), /* preferModelValue */ true);
 81.2598 +            }
 81.2599 +
 81.2600 +            // Workaround for IE9 bug
 81.2601 +            ko.utils.ensureSelectElementIsRenderedCorrectly(element);
 81.2602 +        }
 81.2603 +    }
 81.2604 +};
 81.2605 +ko.bindingHandlers['options'].optionValueDomDataKey = '__ko.optionValueDomData__';
 81.2606 +ko.bindingHandlers['selectedOptions'] = {
 81.2607 +    'init': function (element, valueAccessor, allBindingsAccessor) {
 81.2608 +        ko.utils.registerEventHandler(element, "change", function () {
 81.2609 +            var value = valueAccessor(), valueToWrite = [];
 81.2610 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
 81.2611 +                if (node.selected)
 81.2612 +                    valueToWrite.push(ko.selectExtensions.readValue(node));
 81.2613 +            });
 81.2614 +            ko.expressionRewriting.writeValueToProperty(value, allBindingsAccessor, 'value', valueToWrite);
 81.2615 +        });
 81.2616 +    },
 81.2617 +    'update': function (element, valueAccessor) {
 81.2618 +        if (ko.utils.tagNameLower(element) != "select")
 81.2619 +            throw new Error("values binding applies only to SELECT elements");
 81.2620 +
 81.2621 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
 81.2622 +        if (newValue && typeof newValue.length == "number") {
 81.2623 +            ko.utils.arrayForEach(element.getElementsByTagName("option"), function(node) {
 81.2624 +                var isSelected = ko.utils.arrayIndexOf(newValue, ko.selectExtensions.readValue(node)) >= 0;
 81.2625 +                ko.utils.setOptionNodeSelectionState(node, isSelected);
 81.2626 +            });
 81.2627 +        }
 81.2628 +    }
 81.2629 +};
 81.2630 +ko.bindingHandlers['style'] = {
 81.2631 +    'update': function (element, valueAccessor) {
 81.2632 +        var value = ko.utils.unwrapObservable(valueAccessor() || {});
 81.2633 +        for (var styleName in value) {
 81.2634 +            if (typeof styleName == "string") {
 81.2635 +                var styleValue = ko.utils.unwrapObservable(value[styleName]);
 81.2636 +                element.style[styleName] = styleValue || ""; // Empty string removes the value, whereas null/undefined have no effect
 81.2637 +            }
 81.2638 +        }
 81.2639 +    }
 81.2640 +};
 81.2641 +ko.bindingHandlers['submit'] = {
 81.2642 +    'init': function (element, valueAccessor, allBindingsAccessor, viewModel) {
 81.2643 +        if (typeof valueAccessor() != "function")
 81.2644 +            throw new Error("The value for a submit binding must be a function");
 81.2645 +        ko.utils.registerEventHandler(element, "submit", function (event) {
 81.2646 +            var handlerReturnValue;
 81.2647 +            var value = valueAccessor();
 81.2648 +            try { handlerReturnValue = value.call(viewModel, element); }
 81.2649 +            finally {
 81.2650 +                if (handlerReturnValue !== true) { // Normally we want to prevent default action. Developer can override this be explicitly returning true.
 81.2651 +                    if (event.preventDefault)
 81.2652 +                        event.preventDefault();
 81.2653 +                    else
 81.2654 +                        event.returnValue = false;
 81.2655 +                }
 81.2656 +            }
 81.2657 +        });
 81.2658 +    }
 81.2659 +};
 81.2660 +ko.bindingHandlers['text'] = {
 81.2661 +    'update': function (element, valueAccessor) {
 81.2662 +        ko.utils.setTextContent(element, valueAccessor());
 81.2663 +    }
 81.2664 +};
 81.2665 +ko.virtualElements.allowedBindings['text'] = true;
 81.2666 +ko.bindingHandlers['uniqueName'] = {
 81.2667 +    'init': function (element, valueAccessor) {
 81.2668 +        if (valueAccessor()) {
 81.2669 +            var name = "ko_unique_" + (++ko.bindingHandlers['uniqueName'].currentIndex);
 81.2670 +            ko.utils.setElementName(element, name);
 81.2671 +        }
 81.2672 +    }
 81.2673 +};
 81.2674 +ko.bindingHandlers['uniqueName'].currentIndex = 0;
 81.2675 +ko.bindingHandlers['value'] = {
 81.2676 +    'init': function (element, valueAccessor, allBindingsAccessor) {
 81.2677 +        // Always catch "change" event; possibly other events too if asked
 81.2678 +        var eventsToCatch = ["change"];
 81.2679 +        var requestedEventsToCatch = allBindingsAccessor()["valueUpdate"];
 81.2680 +        var propertyChangedFired = false;
 81.2681 +        if (requestedEventsToCatch) {
 81.2682 +            if (typeof requestedEventsToCatch == "string") // Allow both individual event names, and arrays of event names
 81.2683 +                requestedEventsToCatch = [requestedEventsToCatch];
 81.2684 +            ko.utils.arrayPushAll(eventsToCatch, requestedEventsToCatch);
 81.2685 +            eventsToCatch = ko.utils.arrayGetDistinctValues(eventsToCatch);
 81.2686 +        }
 81.2687 +
 81.2688 +        var valueUpdateHandler = function() {
 81.2689 +            propertyChangedFired = false;
 81.2690 +            var modelValue = valueAccessor();
 81.2691 +            var elementValue = ko.selectExtensions.readValue(element);
 81.2692 +            ko.expressionRewriting.writeValueToProperty(modelValue, allBindingsAccessor, 'value', elementValue);
 81.2693 +        }
 81.2694 +
 81.2695 +        // Workaround for https://github.com/SteveSanderson/knockout/issues/122
 81.2696 +        // IE doesn't fire "change" events on textboxes if the user selects a value from its autocomplete list
 81.2697 +        var ieAutoCompleteHackNeeded = ko.utils.ieVersion && element.tagName.toLowerCase() == "input" && element.type == "text"
 81.2698 +                                       && element.autocomplete != "off" && (!element.form || element.form.autocomplete != "off");
 81.2699 +        if (ieAutoCompleteHackNeeded && ko.utils.arrayIndexOf(eventsToCatch, "propertychange") == -1) {
 81.2700 +            ko.utils.registerEventHandler(element, "propertychange", function () { propertyChangedFired = true });
 81.2701 +            ko.utils.registerEventHandler(element, "blur", function() {
 81.2702 +                if (propertyChangedFired) {
 81.2703 +                    valueUpdateHandler();
 81.2704 +                }
 81.2705 +            });
 81.2706 +        }
 81.2707 +
 81.2708 +        ko.utils.arrayForEach(eventsToCatch, function(eventName) {
 81.2709 +            // The syntax "after<eventname>" means "run the handler asynchronously after the event"
 81.2710 +            // This is useful, for example, to catch "keydown" events after the browser has updated the control
 81.2711 +            // (otherwise, ko.selectExtensions.readValue(this) will receive the control's value *before* the key event)
 81.2712 +            var handler = valueUpdateHandler;
 81.2713 +            if (ko.utils.stringStartsWith(eventName, "after")) {
 81.2714 +                handler = function() { setTimeout(valueUpdateHandler, 0) };
 81.2715 +                eventName = eventName.substring("after".length);
 81.2716 +            }
 81.2717 +            ko.utils.registerEventHandler(element, eventName, handler);
 81.2718 +        });
 81.2719 +    },
 81.2720 +    'update': function (element, valueAccessor) {
 81.2721 +        var valueIsSelectOption = ko.utils.tagNameLower(element) === "select";
 81.2722 +        var newValue = ko.utils.unwrapObservable(valueAccessor());
 81.2723 +        var elementValue = ko.selectExtensions.readValue(element);
 81.2724 +        var valueHasChanged = (newValue != elementValue);
 81.2725 +
 81.2726 +        // JavaScript's 0 == "" behavious is unfortunate here as it prevents writing 0 to an empty text box (loose equality suggests the values are the same).
 81.2727 +        // We don't want to do a strict equality comparison as that is more confusing for developers in certain cases, so we specifically special case 0 != "" here.
 81.2728 +        if ((newValue === 0) && (elementValue !== 0) && (elementValue !== "0"))
 81.2729 +            valueHasChanged = true;
 81.2730 +
 81.2731 +        if (valueHasChanged) {
 81.2732 +            var applyValueAction = function () { ko.selectExtensions.writeValue(element, newValue); };
 81.2733 +            applyValueAction();
 81.2734 +
 81.2735 +            // Workaround for IE6 bug: It won't reliably apply values to SELECT nodes during the same execution thread
 81.2736 +            // right after you've changed the set of OPTION nodes on it. So for that node type, we'll schedule a second thread
 81.2737 +            // to apply the value as well.
 81.2738 +            var alsoApplyAsynchronously = valueIsSelectOption;
 81.2739 +            if (alsoApplyAsynchronously)
 81.2740 +                setTimeout(applyValueAction, 0);
 81.2741 +        }
 81.2742 +
 81.2743 +        // If you try to set a model value that can't be represented in an already-populated dropdown, reject that change,
 81.2744 +        // because you're not allowed to have a model value that disagrees with a visible UI selection.
 81.2745 +        if (valueIsSelectOption && (element.length > 0))
 81.2746 +            ensureDropdownSelectionIsConsistentWithModelValue(element, newValue, /* preferModelValue */ false);
 81.2747 +    }
 81.2748 +};
 81.2749 +ko.bindingHandlers['visible'] = {
 81.2750 +    'update': function (element, valueAccessor) {
 81.2751 +        var value = ko.utils.unwrapObservable(valueAccessor());
 81.2752 +        var isCurrentlyVisible = !(element.style.display == "none");
 81.2753 +        if (value && !isCurrentlyVisible)
 81.2754 +            element.style.display = "";
 81.2755 +        else if ((!value) && isCurrentlyVisible)
 81.2756 +            element.style.display = "none";
 81.2757 +    }
 81.2758 +};
 81.2759 +// 'click' is just a shorthand for the usual full-length event:{click:handler}
 81.2760 +makeEventHandlerShortcut('click');
 81.2761 +// If you want to make a custom template engine,
 81.2762 +//
 81.2763 +// [1] Inherit from this class (like ko.nativeTemplateEngine does)
 81.2764 +// [2] Override 'renderTemplateSource', supplying a function with this signature:
 81.2765 +//
 81.2766 +//        function (templateSource, bindingContext, options) {
 81.2767 +//            // - templateSource.text() is the text of the template you should render
 81.2768 +//            // - bindingContext.$data is the data you should pass into the template
 81.2769 +//            //   - you might also want to make bindingContext.$parent, bindingContext.$parents,
 81.2770 +//            //     and bindingContext.$root available in the template too
 81.2771 +//            // - options gives you access to any other properties set on "data-bind: { template: options }"
 81.2772 +//            //
 81.2773 +//            // Return value: an array of DOM nodes
 81.2774 +//        }
 81.2775 +//
 81.2776 +// [3] Override 'createJavaScriptEvaluatorBlock', supplying a function with this signature:
 81.2777 +//
 81.2778 +//        function (script) {
 81.2779 +//            // Return value: Whatever syntax means "Evaluate the JavaScript statement 'script' and output the result"
 81.2780 +//            //               For example, the jquery.tmpl template engine converts 'someScript' to '${ someScript }'
 81.2781 +//        }
 81.2782 +//
 81.2783 +//     This is only necessary if you want to allow data-bind attributes to reference arbitrary template variables.
 81.2784 +//     If you don't want to allow that, you can set the property 'allowTemplateRewriting' to false (like ko.nativeTemplateEngine does)
 81.2785 +//     and then you don't need to override 'createJavaScriptEvaluatorBlock'.
 81.2786 +
 81.2787 +ko.templateEngine = function () { };
 81.2788 +
 81.2789 +ko.templateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
 81.2790 +    throw new Error("Override renderTemplateSource");
 81.2791 +};
 81.2792 +
 81.2793 +ko.templateEngine.prototype['createJavaScriptEvaluatorBlock'] = function (script) {
 81.2794 +    throw new Error("Override createJavaScriptEvaluatorBlock");
 81.2795 +};
 81.2796 +
 81.2797 +ko.templateEngine.prototype['makeTemplateSource'] = function(template, templateDocument) {
 81.2798 +    // Named template
 81.2799 +    if (typeof template == "string") {
 81.2800 +        templateDocument = templateDocument || document;
 81.2801 +        var elem = templateDocument.getElementById(template);
 81.2802 +        if (!elem)
 81.2803 +            throw new Error("Cannot find template with ID " + template);
 81.2804 +        return new ko.templateSources.domElement(elem);
 81.2805 +    } else if ((template.nodeType == 1) || (template.nodeType == 8)) {
 81.2806 +        // Anonymous template
 81.2807 +        return new ko.templateSources.anonymousTemplate(template);
 81.2808 +    } else
 81.2809 +        throw new Error("Unknown template type: " + template);
 81.2810 +};
 81.2811 +
 81.2812 +ko.templateEngine.prototype['renderTemplate'] = function (template, bindingContext, options, templateDocument) {
 81.2813 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
 81.2814 +    return this['renderTemplateSource'](templateSource, bindingContext, options);
 81.2815 +};
 81.2816 +
 81.2817 +ko.templateEngine.prototype['isTemplateRewritten'] = function (template, templateDocument) {
 81.2818 +    // Skip rewriting if requested
 81.2819 +    if (this['allowTemplateRewriting'] === false)
 81.2820 +        return true;
 81.2821 +    return this['makeTemplateSource'](template, templateDocument)['data']("isRewritten");
 81.2822 +};
 81.2823 +
 81.2824 +ko.templateEngine.prototype['rewriteTemplate'] = function (template, rewriterCallback, templateDocument) {
 81.2825 +    var templateSource = this['makeTemplateSource'](template, templateDocument);
 81.2826 +    var rewritten = rewriterCallback(templateSource['text']());
 81.2827 +    templateSource['text'](rewritten);
 81.2828 +    templateSource['data']("isRewritten", true);
 81.2829 +};
 81.2830 +
 81.2831 +ko.exportSymbol('templateEngine', ko.templateEngine);
 81.2832 +
 81.2833 +ko.templateRewriting = (function () {
 81.2834 +    var memoizeDataBindingAttributeSyntaxRegex = /(<[a-z]+\d*(\s+(?!data-bind=)[a-z0-9\-]+(=(\"[^\"]*\"|\'[^\']*\'))?)*\s+)data-bind=(["'])([\s\S]*?)\5/gi;
 81.2835 +    var memoizeVirtualContainerBindingSyntaxRegex = /<!--\s*ko\b\s*([\s\S]*?)\s*-->/g;
 81.2836 +
 81.2837 +    function validateDataBindValuesForRewriting(keyValueArray) {
 81.2838 +        var allValidators = ko.expressionRewriting.bindingRewriteValidators;
 81.2839 +        for (var i = 0; i < keyValueArray.length; i++) {
 81.2840 +            var key = keyValueArray[i]['key'];
 81.2841 +            if (allValidators.hasOwnProperty(key)) {
 81.2842 +                var validator = allValidators[key];
 81.2843 +
 81.2844 +                if (typeof validator === "function") {
 81.2845 +                    var possibleErrorMessage = validator(keyValueArray[i]['value']);
 81.2846 +                    if (possibleErrorMessage)
 81.2847 +                        throw new Error(possibleErrorMessage);
 81.2848 +                } else if (!validator) {
 81.2849 +                    throw new Error("This template engine does not support the '" + key + "' binding within its templates");
 81.2850 +                }
 81.2851 +            }
 81.2852 +        }
 81.2853 +    }
 81.2854 +
 81.2855 +    function constructMemoizedTagReplacement(dataBindAttributeValue, tagToRetain, templateEngine) {
 81.2856 +        var dataBindKeyValueArray = ko.expressionRewriting.parseObjectLiteral(dataBindAttributeValue);
 81.2857 +        validateDataBindValuesForRewriting(dataBindKeyValueArray);
 81.2858 +        var rewrittenDataBindAttributeValue = ko.expressionRewriting.preProcessBindings(dataBindKeyValueArray);
 81.2859 +
 81.2860 +        // For no obvious reason, Opera fails to evaluate rewrittenDataBindAttributeValue unless it's wrapped in an additional
 81.2861 +        // anonymous function, even though Opera's built-in debugger can evaluate it anyway. No other browser requires this
 81.2862 +        // extra indirection.
 81.2863 +        var applyBindingsToNextSiblingScript =
 81.2864 +            "ko.__tr_ambtns(function($context,$element){return(function(){return{ " + rewrittenDataBindAttributeValue + " } })()})";
 81.2865 +        return templateEngine['createJavaScriptEvaluatorBlock'](applyBindingsToNextSiblingScript) + tagToRetain;
 81.2866 +    }
 81.2867 +
 81.2868 +    return {
 81.2869 +        ensureTemplateIsRewritten: function (template, templateEngine, templateDocument) {
 81.2870 +            if (!templateEngine['isTemplateRewritten'](template, templateDocument))
 81.2871 +                templateEngine['rewriteTemplate'](template, function (htmlString) {
 81.2872 +                    return ko.templateRewriting.memoizeBindingAttributeSyntax(htmlString, templateEngine);
 81.2873 +                }, templateDocument);
 81.2874 +        },
 81.2875 +
 81.2876 +        memoizeBindingAttributeSyntax: function (htmlString, templateEngine) {
 81.2877 +            return htmlString.replace(memoizeDataBindingAttributeSyntaxRegex, function () {
 81.2878 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[6], /* tagToRetain: */ arguments[1], templateEngine);
 81.2879 +            }).replace(memoizeVirtualContainerBindingSyntaxRegex, function() {
 81.2880 +                return constructMemoizedTagReplacement(/* dataBindAttributeValue: */ arguments[1], /* tagToRetain: */ "<!-- ko -->", templateEngine);
 81.2881 +            });
 81.2882 +        },
 81.2883 +
 81.2884 +        applyMemoizedBindingsToNextSibling: function (bindings) {
 81.2885 +            return ko.memoization.memoize(function (domNode, bindingContext) {
 81.2886 +                if (domNode.nextSibling)
 81.2887 +                    ko.applyBindingsToNode(domNode.nextSibling, bindings, bindingContext);
 81.2888 +            });
 81.2889 +        }
 81.2890 +    }
 81.2891 +})();
 81.2892 +
 81.2893 +
 81.2894 +// Exported only because it has to be referenced by string lookup from within rewritten template
 81.2895 +ko.exportSymbol('__tr_ambtns', ko.templateRewriting.applyMemoizedBindingsToNextSibling);
 81.2896 +(function() {
 81.2897 +    // A template source represents a read/write way of accessing a template. This is to eliminate the need for template loading/saving
 81.2898 +    // logic to be duplicated in every template engine (and means they can all work with anonymous templates, etc.)
 81.2899 +    //
 81.2900 +    // Two are provided by default:
 81.2901 +    //  1. ko.templateSources.domElement       - reads/writes the text content of an arbitrary DOM element
 81.2902 +    //  2. ko.templateSources.anonymousElement - uses ko.utils.domData to read/write text *associated* with the DOM element, but
 81.2903 +    //                                           without reading/writing the actual element text content, since it will be overwritten
 81.2904 +    //                                           with the rendered template output.
 81.2905 +    // You can implement your own template source if you want to fetch/store templates somewhere other than in DOM elements.
 81.2906 +    // Template sources need to have the following functions:
 81.2907 +    //   text() 			- returns the template text from your storage location
 81.2908 +    //   text(value)		- writes the supplied template text to your storage location
 81.2909 +    //   data(key)			- reads values stored using data(key, value) - see below
 81.2910 +    //   data(key, value)	- associates "value" with this template and the key "key". Is used to store information like "isRewritten".
 81.2911 +    //
 81.2912 +    // Optionally, template sources can also have the following functions:
 81.2913 +    //   nodes()            - returns a DOM element containing the nodes of this template, where available
 81.2914 +    //   nodes(value)       - writes the given DOM element to your storage location
 81.2915 +    // If a DOM element is available for a given template source, template engines are encouraged to use it in preference over text()
 81.2916 +    // for improved speed. However, all templateSources must supply text() even if they don't supply nodes().
 81.2917 +    //
 81.2918 +    // Once you've implemented a templateSource, make your template engine use it by subclassing whatever template engine you were
 81.2919 +    // using and overriding "makeTemplateSource" to return an instance of your custom template source.
 81.2920 +
 81.2921 +    ko.templateSources = {};
 81.2922 +
 81.2923 +    // ---- ko.templateSources.domElement -----
 81.2924 +
 81.2925 +    ko.templateSources.domElement = function(element) {
 81.2926 +        this.domElement = element;
 81.2927 +    }
 81.2928 +
 81.2929 +    ko.templateSources.domElement.prototype['text'] = function(/* valueToWrite */) {
 81.2930 +        var tagNameLower = ko.utils.tagNameLower(this.domElement),
 81.2931 +            elemContentsProperty = tagNameLower === "script" ? "text"
 81.2932 +                                 : tagNameLower === "textarea" ? "value"
 81.2933 +                                 : "innerHTML";
 81.2934 +
 81.2935 +        if (arguments.length == 0) {
 81.2936 +            return this.domElement[elemContentsProperty];
 81.2937 +        } else {
 81.2938 +            var valueToWrite = arguments[0];
 81.2939 +            if (elemContentsProperty === "innerHTML")
 81.2940 +                ko.utils.setHtml(this.domElement, valueToWrite);
 81.2941 +            else
 81.2942 +                this.domElement[elemContentsProperty] = valueToWrite;
 81.2943 +        }
 81.2944 +    };
 81.2945 +
 81.2946 +    ko.templateSources.domElement.prototype['data'] = function(key /*, valueToWrite */) {
 81.2947 +        if (arguments.length === 1) {
 81.2948 +            return ko.utils.domData.get(this.domElement, "templateSourceData_" + key);
 81.2949 +        } else {
 81.2950 +            ko.utils.domData.set(this.domElement, "templateSourceData_" + key, arguments[1]);
 81.2951 +        }
 81.2952 +    };
 81.2953 +
 81.2954 +    // ---- ko.templateSources.anonymousTemplate -----
 81.2955 +    // Anonymous templates are normally saved/retrieved as DOM nodes through "nodes".
 81.2956 +    // For compatibility, you can also read "text"; it will be serialized from the nodes on demand.
 81.2957 +    // Writing to "text" is still supported, but then the template data will not be available as DOM nodes.
 81.2958 +
 81.2959 +    var anonymousTemplatesDomDataKey = "__ko_anon_template__";
 81.2960 +    ko.templateSources.anonymousTemplate = function(element) {
 81.2961 +        this.domElement = element;
 81.2962 +    }
 81.2963 +    ko.templateSources.anonymousTemplate.prototype = new ko.templateSources.domElement();
 81.2964 +    ko.templateSources.anonymousTemplate.prototype['text'] = function(/* valueToWrite */) {
 81.2965 +        if (arguments.length == 0) {
 81.2966 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
 81.2967 +            if (templateData.textData === undefined && templateData.containerData)
 81.2968 +                templateData.textData = templateData.containerData.innerHTML;
 81.2969 +            return templateData.textData;
 81.2970 +        } else {
 81.2971 +            var valueToWrite = arguments[0];
 81.2972 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {textData: valueToWrite});
 81.2973 +        }
 81.2974 +    };
 81.2975 +    ko.templateSources.domElement.prototype['nodes'] = function(/* valueToWrite */) {
 81.2976 +        if (arguments.length == 0) {
 81.2977 +            var templateData = ko.utils.domData.get(this.domElement, anonymousTemplatesDomDataKey) || {};
 81.2978 +            return templateData.containerData;
 81.2979 +        } else {
 81.2980 +            var valueToWrite = arguments[0];
 81.2981 +            ko.utils.domData.set(this.domElement, anonymousTemplatesDomDataKey, {containerData: valueToWrite});
 81.2982 +        }
 81.2983 +    };
 81.2984 +
 81.2985 +    ko.exportSymbol('templateSources', ko.templateSources);
 81.2986 +    ko.exportSymbol('templateSources.domElement', ko.templateSources.domElement);
 81.2987 +    ko.exportSymbol('templateSources.anonymousTemplate', ko.templateSources.anonymousTemplate);
 81.2988 +})();
 81.2989 +(function () {
 81.2990 +    var _templateEngine;
 81.2991 +    ko.setTemplateEngine = function (templateEngine) {
 81.2992 +        if ((templateEngine != undefined) && !(templateEngine instanceof ko.templateEngine))
 81.2993 +            throw new Error("templateEngine must inherit from ko.templateEngine");
 81.2994 +        _templateEngine = templateEngine;
 81.2995 +    }
 81.2996 +
 81.2997 +    function invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, action) {
 81.2998 +        var node, nextInQueue = firstNode, firstOutOfRangeNode = ko.virtualElements.nextSibling(lastNode);
 81.2999 +        while (nextInQueue && ((node = nextInQueue) !== firstOutOfRangeNode)) {
 81.3000 +            nextInQueue = ko.virtualElements.nextSibling(node);
 81.3001 +            if (node.nodeType === 1 || node.nodeType === 8)
 81.3002 +                action(node);
 81.3003 +        }
 81.3004 +    }
 81.3005 +
 81.3006 +    function activateBindingsOnContinuousNodeArray(continuousNodeArray, bindingContext) {
 81.3007 +        // To be used on any nodes that have been rendered by a template and have been inserted into some parent element
 81.3008 +        // Walks through continuousNodeArray (which *must* be continuous, i.e., an uninterrupted sequence of sibling nodes, because
 81.3009 +        // the algorithm for walking them relies on this), and for each top-level item in the virtual-element sense,
 81.3010 +        // (1) Does a regular "applyBindings" to associate bindingContext with this node and to activate any non-memoized bindings
 81.3011 +        // (2) Unmemoizes any memos in the DOM subtree (e.g., to activate bindings that had been memoized during template rewriting)
 81.3012 +
 81.3013 +        if (continuousNodeArray.length) {
 81.3014 +            var firstNode = continuousNodeArray[0], lastNode = continuousNodeArray[continuousNodeArray.length - 1];
 81.3015 +
 81.3016 +            // Need to applyBindings *before* unmemoziation, because unmemoization might introduce extra nodes (that we don't want to re-bind)
 81.3017 +            // whereas a regular applyBindings won't introduce new memoized nodes
 81.3018 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
 81.3019 +                ko.applyBindings(bindingContext, node);
 81.3020 +            });
 81.3021 +            invokeForEachNodeOrCommentInContinuousRange(firstNode, lastNode, function(node) {
 81.3022 +                ko.memoization.unmemoizeDomNodeAndDescendants(node, [bindingContext]);
 81.3023 +            });
 81.3024 +        }
 81.3025 +    }
 81.3026 +
 81.3027 +    function getFirstNodeFromPossibleArray(nodeOrNodeArray) {
 81.3028 +        return nodeOrNodeArray.nodeType ? nodeOrNodeArray
 81.3029 +                                        : nodeOrNodeArray.length > 0 ? nodeOrNodeArray[0]
 81.3030 +                                        : null;
 81.3031 +    }
 81.3032 +
 81.3033 +    function executeTemplate(targetNodeOrNodeArray, renderMode, template, bindingContext, options) {
 81.3034 +        options = options || {};
 81.3035 +        var firstTargetNode = targetNodeOrNodeArray && getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
 81.3036 +        var templateDocument = firstTargetNode && firstTargetNode.ownerDocument;
 81.3037 +        var templateEngineToUse = (options['templateEngine'] || _templateEngine);
 81.3038 +        ko.templateRewriting.ensureTemplateIsRewritten(template, templateEngineToUse, templateDocument);
 81.3039 +        var renderedNodesArray = templateEngineToUse['renderTemplate'](template, bindingContext, options, templateDocument);
 81.3040 +
 81.3041 +        // Loosely check result is an array of DOM nodes
 81.3042 +        if ((typeof renderedNodesArray.length != "number") || (renderedNodesArray.length > 0 && typeof renderedNodesArray[0].nodeType != "number"))
 81.3043 +            throw new Error("Template engine must return an array of DOM nodes");
 81.3044 +
 81.3045 +        var haveAddedNodesToParent = false;
 81.3046 +        switch (renderMode) {
 81.3047 +            case "replaceChildren":
 81.3048 +                ko.virtualElements.setDomNodeChildren(targetNodeOrNodeArray, renderedNodesArray);
 81.3049 +                haveAddedNodesToParent = true;
 81.3050 +                break;
 81.3051 +            case "replaceNode":
 81.3052 +                ko.utils.replaceDomNodes(targetNodeOrNodeArray, renderedNodesArray);
 81.3053 +                haveAddedNodesToParent = true;
 81.3054 +                break;
 81.3055 +            case "ignoreTargetNode": break;
 81.3056 +            default:
 81.3057 +                throw new Error("Unknown renderMode: " + renderMode);
 81.3058 +        }
 81.3059 +
 81.3060 +        if (haveAddedNodesToParent) {
 81.3061 +            activateBindingsOnContinuousNodeArray(renderedNodesArray, bindingContext);
 81.3062 +            if (options['afterRender'])
 81.3063 +                ko.dependencyDetection.ignore(options['afterRender'], null, [renderedNodesArray, bindingContext['$data']]);
 81.3064 +        }
 81.3065 +
 81.3066 +        return renderedNodesArray;
 81.3067 +    }
 81.3068 +
 81.3069 +    ko.renderTemplate = function (template, dataOrBindingContext, options, targetNodeOrNodeArray, renderMode) {
 81.3070 +        options = options || {};
 81.3071 +        if ((options['templateEngine'] || _templateEngine) == undefined)
 81.3072 +            throw new Error("Set a template engine before calling renderTemplate");
 81.3073 +        renderMode = renderMode || "replaceChildren";
 81.3074 +
 81.3075 +        if (targetNodeOrNodeArray) {
 81.3076 +            var firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
 81.3077 +
 81.3078 +            var whenToDispose = function () { return (!firstTargetNode) || !ko.utils.domNodeIsAttachedToDocument(firstTargetNode); }; // Passive disposal (on next evaluation)
 81.3079 +            var activelyDisposeWhenNodeIsRemoved = (firstTargetNode && renderMode == "replaceNode") ? firstTargetNode.parentNode : firstTargetNode;
 81.3080 +
 81.3081 +            return ko.dependentObservable( // So the DOM is automatically updated when any dependency changes
 81.3082 +                function () {
 81.3083 +                    // Ensure we've got a proper binding context to work with
 81.3084 +                    var bindingContext = (dataOrBindingContext && (dataOrBindingContext instanceof ko.bindingContext))
 81.3085 +                        ? dataOrBindingContext
 81.3086 +                        : new ko.bindingContext(ko.utils.unwrapObservable(dataOrBindingContext));
 81.3087 +
 81.3088 +                    // Support selecting template as a function of the data being rendered
 81.3089 +                    var templateName = typeof(template) == 'function' ? template(bindingContext['$data'], bindingContext) : template;
 81.3090 +
 81.3091 +                    var renderedNodesArray = executeTemplate(targetNodeOrNodeArray, renderMode, templateName, bindingContext, options);
 81.3092 +                    if (renderMode == "replaceNode") {
 81.3093 +                        targetNodeOrNodeArray = renderedNodesArray;
 81.3094 +                        firstTargetNode = getFirstNodeFromPossibleArray(targetNodeOrNodeArray);
 81.3095 +                    }
 81.3096 +                },
 81.3097 +                null,
 81.3098 +                { disposeWhen: whenToDispose, disposeWhenNodeIsRemoved: activelyDisposeWhenNodeIsRemoved }
 81.3099 +            );
 81.3100 +        } else {
 81.3101 +            // We don't yet have a DOM node to evaluate, so use a memo and render the template later when there is a DOM node
 81.3102 +            return ko.memoization.memoize(function (domNode) {
 81.3103 +                ko.renderTemplate(template, dataOrBindingContext, options, domNode, "replaceNode");
 81.3104 +            });
 81.3105 +        }
 81.3106 +    };
 81.3107 +
 81.3108 +    ko.renderTemplateForEach = function (template, arrayOrObservableArray, options, targetNode, parentBindingContext) {
 81.3109 +        // Since setDomNodeChildrenFromArrayMapping always calls executeTemplateForArrayItem and then
 81.3110 +        // activateBindingsCallback for added items, we can store the binding context in the former to use in the latter.
 81.3111 +        var arrayItemContext;
 81.3112 +
 81.3113 +        // This will be called by setDomNodeChildrenFromArrayMapping to get the nodes to add to targetNode
 81.3114 +        var executeTemplateForArrayItem = function (arrayValue, index) {
 81.3115 +            // Support selecting template as a function of the data being rendered
 81.3116 +            arrayItemContext = parentBindingContext['createChildContext'](ko.utils.unwrapObservable(arrayValue), options['as']);
 81.3117 +            arrayItemContext['$index'] = index;
 81.3118 +            var templateName = typeof(template) == 'function' ? template(arrayValue, arrayItemContext) : template;
 81.3119 +            return executeTemplate(null, "ignoreTargetNode", templateName, arrayItemContext, options);
 81.3120 +        }
 81.3121 +
 81.3122 +        // This will be called whenever setDomNodeChildrenFromArrayMapping has added nodes to targetNode
 81.3123 +        var activateBindingsCallback = function(arrayValue, addedNodesArray, index) {
 81.3124 +            activateBindingsOnContinuousNodeArray(addedNodesArray, arrayItemContext);
 81.3125 +            if (options['afterRender'])
 81.3126 +                options['afterRender'](addedNodesArray, arrayValue);
 81.3127 +        };
 81.3128 +
 81.3129 +        return ko.dependentObservable(function () {
 81.3130 +            var unwrappedArray = ko.utils.unwrapObservable(arrayOrObservableArray) || [];
 81.3131 +            if (typeof unwrappedArray.length == "undefined") // Coerce single value into array
 81.3132 +                unwrappedArray = [unwrappedArray];
 81.3133 +
 81.3134 +            // Filter out any entries marked as destroyed
 81.3135 +            var filteredArray = ko.utils.arrayFilter(unwrappedArray, function(item) {
 81.3136 +                return options['includeDestroyed'] || item === undefined || item === null || !ko.utils.unwrapObservable(item['_destroy']);
 81.3137 +            });
 81.3138 +
 81.3139 +            // Call setDomNodeChildrenFromArrayMapping, ignoring any observables unwrapped within (most likely from a callback function).
 81.3140 +            // If the array items are observables, though, they will be unwrapped in executeTemplateForArrayItem and managed within setDomNodeChildrenFromArrayMapping.
 81.3141 +            ko.dependencyDetection.ignore(ko.utils.setDomNodeChildrenFromArrayMapping, null, [targetNode, filteredArray, executeTemplateForArrayItem, options, activateBindingsCallback]);
 81.3142 +
 81.3143 +        }, null, { disposeWhenNodeIsRemoved: targetNode });
 81.3144 +    };
 81.3145 +
 81.3146 +    var templateComputedDomDataKey = '__ko__templateComputedDomDataKey__';
 81.3147 +    function disposeOldComputedAndStoreNewOne(element, newComputed) {
 81.3148 +        var oldComputed = ko.utils.domData.get(element, templateComputedDomDataKey);
 81.3149 +        if (oldComputed && (typeof(oldComputed.dispose) == 'function'))
 81.3150 +            oldComputed.dispose();
 81.3151 +        ko.utils.domData.set(element, templateComputedDomDataKey, (newComputed && newComputed.isActive()) ? newComputed : undefined);
 81.3152 +    }
 81.3153 +
 81.3154 +    ko.bindingHandlers['template'] = {
 81.3155 +        'init': function(element, valueAccessor) {
 81.3156 +            // Support anonymous templates
 81.3157 +            var bindingValue = ko.utils.unwrapObservable(valueAccessor());
 81.3158 +            if ((typeof bindingValue != "string") && (!bindingValue['name']) && (element.nodeType == 1 || element.nodeType == 8)) {
 81.3159 +                // It's an anonymous template - store the element contents, then clear the element
 81.3160 +                var templateNodes = element.nodeType == 1 ? element.childNodes : ko.virtualElements.childNodes(element),
 81.3161 +                    container = ko.utils.moveCleanedNodesToContainerElement(templateNodes); // This also removes the nodes from their current parent
 81.3162 +                new ko.templateSources.anonymousTemplate(element)['nodes'](container);
 81.3163 +            }
 81.3164 +            return { 'controlsDescendantBindings': true };
 81.3165 +        },
 81.3166 +        'update': function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {
 81.3167 +            var templateName = ko.utils.unwrapObservable(valueAccessor()),
 81.3168 +                options = {},
 81.3169 +                shouldDisplay = true,
 81.3170 +                dataValue,
 81.3171 +                templateComputed = null;
 81.3172 +
 81.3173 +            if (typeof templateName != "string") {
 81.3174 +                options = templateName;
 81.3175 +                templateName = options['name'];
 81.3176 +
 81.3177 +                // Support "if"/"ifnot" conditions
 81.3178 +                if ('if' in options)
 81.3179 +                    shouldDisplay = ko.utils.unwrapObservable(options['if']);
 81.3180 +                if (shouldDisplay && 'ifnot' in options)
 81.3181 +                    shouldDisplay = !ko.utils.unwrapObservable(options['ifnot']);
 81.3182 +
 81.3183 +                dataValue = ko.utils.unwrapObservable(options['data']);
 81.3184 +            }
 81.3185 +
 81.3186 +            if ('foreach' in options) {
 81.3187 +                // Render once for each data point (treating data set as empty if shouldDisplay==false)
 81.3188 +                var dataArray = (shouldDisplay && options['foreach']) || [];
 81.3189 +                templateComputed = ko.renderTemplateForEach(templateName || element, dataArray, options, element, bindingContext);
 81.3190 +            } else if (!shouldDisplay) {
 81.3191 +                ko.virtualElements.emptyNode(element);
 81.3192 +            } else {
 81.3193 +                // Render once for this single data point (or use the viewModel if no data was provided)
 81.3194 +                var innerBindingContext = ('data' in options) ?
 81.3195 +                    bindingContext['createChildContext'](dataValue, options['as']) :  // Given an explitit 'data' value, we create a child binding context for it
 81.3196 +                    bindingContext;                                                        // Given no explicit 'data' value, we retain the same binding context
 81.3197 +                templateComputed = ko.renderTemplate(templateName || element, innerBindingContext, options, element);
 81.3198 +            }
 81.3199 +
 81.3200 +            // It only makes sense to have a single template computed per element (otherwise which one should have its output displayed?)
 81.3201 +            disposeOldComputedAndStoreNewOne(element, templateComputed);
 81.3202 +        }
 81.3203 +    };
 81.3204 +
 81.3205 +    // Anonymous templates can't be rewritten. Give a nice error message if you try to do it.
 81.3206 +    ko.expressionRewriting.bindingRewriteValidators['template'] = function(bindingValue) {
 81.3207 +        var parsedBindingValue = ko.expressionRewriting.parseObjectLiteral(bindingValue);
 81.3208 +
 81.3209 +        if ((parsedBindingValue.length == 1) && parsedBindingValue[0]['unknown'])
 81.3210 +            return null; // It looks like a string literal, not an object literal, so treat it as a named template (which is allowed for rewriting)
 81.3211 +
 81.3212 +        if (ko.expressionRewriting.keyValueArrayContainsKey(parsedBindingValue, "name"))
 81.3213 +            return null; // Named templates can be rewritten, so return "no error"
 81.3214 +        return "This template engine does not support anonymous templates nested within its templates";
 81.3215 +    };
 81.3216 +
 81.3217 +    ko.virtualElements.allowedBindings['template'] = true;
 81.3218 +})();
 81.3219 +
 81.3220 +ko.exportSymbol('setTemplateEngine', ko.setTemplateEngine);
 81.3221 +ko.exportSymbol('renderTemplate', ko.renderTemplate);
 81.3222 +
 81.3223 +ko.utils.compareArrays = (function () {
 81.3224 +    var statusNotInOld = 'added', statusNotInNew = 'deleted';
 81.3225 +
 81.3226 +    // Simple calculation based on Levenshtein distance.
 81.3227 +    function compareArrays(oldArray, newArray, dontLimitMoves) {
 81.3228 +        oldArray = oldArray || [];
 81.3229 +        newArray = newArray || [];
 81.3230 +
 81.3231 +        if (oldArray.length <= newArray.length)
 81.3232 +            return compareSmallArrayToBigArray(oldArray, newArray, statusNotInOld, statusNotInNew, dontLimitMoves);
 81.3233 +        else
 81.3234 +            return compareSmallArrayToBigArray(newArray, oldArray, statusNotInNew, statusNotInOld, dontLimitMoves);
 81.3235 +    }
 81.3236 +
 81.3237 +    function compareSmallArrayToBigArray(smlArray, bigArray, statusNotInSml, statusNotInBig, dontLimitMoves) {
 81.3238 +        var myMin = Math.min,
 81.3239 +            myMax = Math.max,
 81.3240 +            editDistanceMatrix = [],
 81.3241 +            smlIndex, smlIndexMax = smlArray.length,
 81.3242 +            bigIndex, bigIndexMax = bigArray.length,
 81.3243 +            compareRange = (bigIndexMax - smlIndexMax) || 1,
 81.3244 +            maxDistance = smlIndexMax + bigIndexMax + 1,
 81.3245 +            thisRow, lastRow,
 81.3246 +            bigIndexMaxForRow, bigIndexMinForRow;
 81.3247 +
 81.3248 +        for (smlIndex = 0; smlIndex <= smlIndexMax; smlIndex++) {
 81.3249 +            lastRow = thisRow;
 81.3250 +            editDistanceMatrix.push(thisRow = []);
 81.3251 +            bigIndexMaxForRow = myMin(bigIndexMax, smlIndex + compareRange);
 81.3252 +            bigIndexMinForRow = myMax(0, smlIndex - 1);
 81.3253 +            for (bigIndex = bigIndexMinForRow; bigIndex <= bigIndexMaxForRow; bigIndex++) {
 81.3254 +                if (!bigIndex)
 81.3255 +                    thisRow[bigIndex] = smlIndex + 1;
 81.3256 +                else if (!smlIndex)  // Top row - transform empty array into new array via additions
 81.3257 +                    thisRow[bigIndex] = bigIndex + 1;
 81.3258 +                else if (smlArray[smlIndex - 1] === bigArray[bigIndex - 1])
 81.3259 +                    thisRow[bigIndex] = lastRow[bigIndex - 1];                  // copy value (no edit)
 81.3260 +                else {
 81.3261 +                    var northDistance = lastRow[bigIndex] || maxDistance;       // not in big (deletion)
 81.3262 +                    var westDistance = thisRow[bigIndex - 1] || maxDistance;    // not in small (addition)
 81.3263 +                    thisRow[bigIndex] = myMin(northDistance, westDistance) + 1;
 81.3264 +                }
 81.3265 +            }
 81.3266 +        }
 81.3267 +
 81.3268 +        var editScript = [], meMinusOne, notInSml = [], notInBig = [];
 81.3269 +        for (smlIndex = smlIndexMax, bigIndex = bigIndexMax; smlIndex || bigIndex;) {
 81.3270 +            meMinusOne = editDistanceMatrix[smlIndex][bigIndex] - 1;
 81.3271 +            if (bigIndex && meMinusOne === editDistanceMatrix[smlIndex][bigIndex-1]) {
 81.3272 +                notInSml.push(editScript[editScript.length] = {     // added
 81.3273 +                    'status': statusNotInSml,
 81.3274 +                    'value': bigArray[--bigIndex],
 81.3275 +                    'index': bigIndex });
 81.3276 +            } else if (smlIndex && meMinusOne === editDistanceMatrix[smlIndex - 1][bigIndex]) {
 81.3277 +                notInBig.push(editScript[editScript.length] = {     // deleted
 81.3278 +                    'status': statusNotInBig,
 81.3279 +                    'value': smlArray[--smlIndex],
 81.3280 +                    'index': smlIndex });
 81.3281 +            } else {
 81.3282 +                editScript.push({
 81.3283 +                    'status': "retained",
 81.3284 +                    'value': bigArray[--bigIndex] });
 81.3285 +                --smlIndex;
 81.3286 +            }
 81.3287 +        }
 81.3288 +
 81.3289 +        if (notInSml.length && notInBig.length) {
 81.3290 +            // Set a limit on the number of consecutive non-matching comparisons; having it a multiple of
 81.3291 +            // smlIndexMax keeps the time complexity of this algorithm linear.
 81.3292 +            var limitFailedCompares = smlIndexMax * 10, failedCompares,
 81.3293 +                a, d, notInSmlItem, notInBigItem;
 81.3294 +            // Go through the items that have been added and deleted and try to find matches between them.
 81.3295 +            for (failedCompares = a = 0; (dontLimitMoves || failedCompares < limitFailedCompares) && (notInSmlItem = notInSml[a]); a++) {
 81.3296 +                for (d = 0; notInBigItem = notInBig[d]; d++) {
 81.3297 +                    if (notInSmlItem['value'] === notInBigItem['value']) {
 81.3298 +                        notInSmlItem['moved'] = notInBigItem['index'];
 81.3299 +                        notInBigItem['moved'] = notInSmlItem['index'];
 81.3300 +                        notInBig.splice(d,1);       // This item is marked as moved; so remove it from notInBig list
 81.3301 +                        failedCompares = d = 0;     // Reset failed compares count because we're checking for consecutive failures
 81.3302 +                        break;
 81.3303 +                    }
 81.3304 +                }
 81.3305 +                failedCompares += d;
 81.3306 +            }
 81.3307 +        }
 81.3308 +        return editScript.reverse();
 81.3309 +    }
 81.3310 +
 81.3311 +    return compareArrays;
 81.3312 +})();
 81.3313 +
 81.3314 +ko.exportSymbol('utils.compareArrays', ko.utils.compareArrays);
 81.3315 +
 81.3316 +(function () {
 81.3317 +    // Objective:
 81.3318 +    // * Given an input array, a container DOM node, and a function from array elements to arrays of DOM nodes,
 81.3319 +    //   map the array elements to arrays of DOM nodes, concatenate together all these arrays, and use them to populate the container DOM node
 81.3320 +    // * Next time we're given the same combination of things (with the array possibly having mutated), update the container DOM node
 81.3321 +    //   so that its children is again the concatenation of the mappings of the array elements, but don't re-map any array elements that we
 81.3322 +    //   previously mapped - retain those nodes, and just insert/delete other ones
 81.3323 +
 81.3324 +    // "callbackAfterAddingNodes" will be invoked after any "mapping"-generated nodes are inserted into the container node
 81.3325 +    // You can use this, for example, to activate bindings on those nodes.
 81.3326 +
 81.3327 +    function fixUpNodesToBeMovedOrRemoved(contiguousNodeArray) {
 81.3328 +        // Before moving, deleting, or replacing a set of nodes that were previously outputted by the "map" function, we have to reconcile
 81.3329 +        // them against what is in the DOM right now. It may be that some of the nodes have already been removed from the document,
 81.3330 +        // or that new nodes might have been inserted in the middle, for example by a binding. Also, there may previously have been
 81.3331 +        // leading comment nodes (created by rewritten string-based templates) that have since been removed during binding.
 81.3332 +        // So, this function translates the old "map" output array into its best guess of what set of current DOM nodes should be removed.
 81.3333 +        //
 81.3334 +        // Rules:
 81.3335 +        //   [A] Any leading nodes that aren't in the document any more should be ignored
 81.3336 +        //       These most likely correspond to memoization nodes that were already removed during binding
 81.3337 +        //       See https://github.com/SteveSanderson/knockout/pull/440
 81.3338 +        //   [B] We want to output a contiguous series of nodes that are still in the document. So, ignore any nodes that
 81.3339 +        //       have already been removed, and include any nodes that have been inserted among the previous collection
 81.3340 +
 81.3341 +        // Rule [A]
 81.3342 +        while (contiguousNodeArray.length && !ko.utils.domNodeIsAttachedToDocument(contiguousNodeArray[0]))
 81.3343 +            contiguousNodeArray.splice(0, 1);
 81.3344 +
 81.3345 +        // Rule [B]
 81.3346 +        if (contiguousNodeArray.length > 1) {
 81.3347 +            // Build up the actual new contiguous node set
 81.3348 +            var current = contiguousNodeArray[0], last = contiguousNodeArray[contiguousNodeArray.length - 1], newContiguousSet = [current];
 81.3349 +            while (current !== last) {
 81.3350 +                current = current.nextSibling;
 81.3351 +                if (!current) // Won't happen, except if the developer has manually removed some DOM elements (then we're in an undefined scenario)
 81.3352 +                    return;
 81.3353 +                newContiguousSet.push(current);
 81.3354 +            }
 81.3355 +
 81.3356 +            // ... then mutate the input array to match this.
 81.3357 +            // (The following line replaces the contents of contiguousNodeArray with newContiguousSet)
 81.3358 +            Array.prototype.splice.apply(contiguousNodeArray, [0, contiguousNodeArray.length].concat(newContiguousSet));
 81.3359 +        }
 81.3360 +        return contiguousNodeArray;
 81.3361 +    }
 81.3362 +
 81.3363 +    function mapNodeAndRefreshWhenChanged(containerNode, mapping, valueToMap, callbackAfterAddingNodes, index) {
 81.3364 +        // Map this array value inside a dependentObservable so we re-map when any dependency changes
 81.3365 +        var mappedNodes = [];
 81.3366 +        var dependentObservable = ko.dependentObservable(function() {
 81.3367 +            var newMappedNodes = mapping(valueToMap, index) || [];
 81.3368 +
 81.3369 +            // On subsequent evaluations, just replace the previously-inserted DOM nodes
 81.3370 +            if (mappedNodes.length > 0) {
 81.3371 +                ko.utils.replaceDomNodes(fixUpNodesToBeMovedOrRemoved(mappedNodes), newMappedNodes);
 81.3372 +                if (callbackAfterAddingNodes)
 81.3373 +                    ko.dependencyDetection.ignore(callbackAfterAddingNodes, null, [valueToMap, newMappedNodes, index]);
 81.3374 +            }
 81.3375 +
 81.3376 +            // Replace the contents of the mappedNodes array, thereby updating the record
 81.3377 +            // of which nodes would be deleted if valueToMap was itself later removed
 81.3378 +            mappedNodes.splice(0, mappedNodes.length);
 81.3379 +            ko.utils.arrayPushAll(mappedNodes, newMappedNodes);
 81.3380 +        }, null, { disposeWhenNodeIsRemoved: containerNode, disposeWhen: function() { return (mappedNodes.length == 0) || !ko.utils.domNodeIsAttachedToDocument(mappedNodes[0]) } });
 81.3381 +        return { mappedNodes : mappedNodes, dependentObservable : (dependentObservable.isActive() ? dependentObservable : undefined) };
 81.3382 +    }
 81.3383 +
 81.3384 +    var lastMappingResultDomDataKey = "setDomNodeChildrenFromArrayMapping_lastMappingResult";
 81.3385 +
 81.3386 +    ko.utils.setDomNodeChildrenFromArrayMapping = function (domNode, array, mapping, options, callbackAfterAddingNodes) {
 81.3387 +        // Compare the provided array against the previous one
 81.3388 +        array = array || [];
 81.3389 +        options = options || {};
 81.3390 +        var isFirstExecution = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) === undefined;
 81.3391 +        var lastMappingResult = ko.utils.domData.get(domNode, lastMappingResultDomDataKey) || [];
 81.3392 +        var lastArray = ko.utils.arrayMap(lastMappingResult, function (x) { return x.arrayEntry; });
 81.3393 +        var editScript = ko.utils.compareArrays(lastArray, array);
 81.3394 +
 81.3395 +        // Build the new mapping result
 81.3396 +        var newMappingResult = [];
 81.3397 +        var lastMappingResultIndex = 0;
 81.3398 +        var newMappingResultIndex = 0;
 81.3399 +
 81.3400 +        var nodesToDelete = [];
 81.3401 +        var itemsToProcess = [];
 81.3402 +        var itemsForBeforeRemoveCallbacks = [];
 81.3403 +        var itemsForMoveCallbacks = [];
 81.3404 +        var itemsForAfterAddCallbacks = [];
 81.3405 +        var mapData;
 81.3406 +
 81.3407 +        function itemMovedOrRetained(editScriptIndex, oldPosition) {
 81.3408 +            mapData = lastMappingResult[oldPosition];
 81.3409 +            if (newMappingResultIndex !== oldPosition)
 81.3410 +                itemsForMoveCallbacks[editScriptIndex] = mapData;
 81.3411 +            // Since updating the index might change the nodes, do so before calling fixUpNodesToBeMovedOrRemoved
 81.3412 +            mapData.indexObservable(newMappingResultIndex++);
 81.3413 +            fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes);
 81.3414 +            newMappingResult.push(mapData);
 81.3415 +            itemsToProcess.push(mapData);
 81.3416 +        }
 81.3417 +
 81.3418 +        function callCallback(callback, items) {
 81.3419 +            if (callback) {
 81.3420 +                for (var i = 0, n = items.length; i < n; i++) {
 81.3421 +                    if (items[i]) {
 81.3422 +                        ko.utils.arrayForEach(items[i].mappedNodes, function(node) {
 81.3423 +                            callback(node, i, items[i].arrayEntry);
 81.3424 +                        });
 81.3425 +                    }
 81.3426 +                }
 81.3427 +            }
 81.3428 +        }
 81.3429 +
 81.3430 +        for (var i = 0, editScriptItem, movedIndex; editScriptItem = editScript[i]; i++) {
 81.3431 +            movedIndex = editScriptItem['moved'];
 81.3432 +            switch (editScriptItem['status']) {
 81.3433 +                case "deleted":
 81.3434 +                    if (movedIndex === undefined) {
 81.3435 +                        mapData = lastMappingResult[lastMappingResultIndex];
 81.3436 +
 81.3437 +                        // Stop tracking changes to the mapping for these nodes
 81.3438 +                        if (mapData.dependentObservable)
 81.3439 +                            mapData.dependentObservable.dispose();
 81.3440 +
 81.3441 +                        // Queue these nodes for later removal
 81.3442 +                        nodesToDelete.push.apply(nodesToDelete, fixUpNodesToBeMovedOrRemoved(mapData.mappedNodes));
 81.3443 +                        if (options['beforeRemove']) {
 81.3444 +                            itemsForBeforeRemoveCallbacks[i] = mapData;
 81.3445 +                            itemsToProcess.push(mapData);
 81.3446 +                        }
 81.3447 +                    }
 81.3448 +                    lastMappingResultIndex++;
 81.3449 +                    break;
 81.3450 +
 81.3451 +                case "retained":
 81.3452 +                    itemMovedOrRetained(i, lastMappingResultIndex++);
 81.3453 +                    break;
 81.3454 +
 81.3455 +                case "added":
 81.3456 +                    if (movedIndex !== undefined) {
 81.3457 +                        itemMovedOrRetained(i, movedIndex);
 81.3458 +                    } else {
 81.3459 +                        mapData = { arrayEntry: editScriptItem['value'], indexObservable: ko.observable(newMappingResultIndex++) };
 81.3460 +                        newMappingResult.push(mapData);
 81.3461 +                        itemsToProcess.push(mapData);
 81.3462 +                        if (!isFirstExecution)
 81.3463 +                            itemsForAfterAddCallbacks[i] = mapData;
 81.3464 +                    }
 81.3465 +                    break;
 81.3466 +            }
 81.3467 +        }
 81.3468 +
 81.3469 +        // Call beforeMove first before any changes have been made to the DOM
 81.3470 +        callCallback(options['beforeMove'], itemsForMoveCallbacks);
 81.3471 +
 81.3472 +        // Next remove nodes for deleted items (or just clean if there's a beforeRemove callback)
 81.3473 +        ko.utils.arrayForEach(nodesToDelete, options['beforeRemove'] ? ko.cleanNode : ko.removeNode);
 81.3474 +
 81.3475 +        // Next add/reorder the remaining items (will include deleted items if there's a beforeRemove callback)
 81.3476 +        for (var i = 0, nextNode = ko.virtualElements.firstChild(domNode), lastNode, node; mapData = itemsToProcess[i]; i++) {
 81.3477 +            // Get nodes for newly added items
 81.3478 +            if (!mapData.mappedNodes)
 81.3479 +                ko.utils.extend(mapData, mapNodeAndRefreshWhenChanged(domNode, mapping, mapData.arrayEntry, callbackAfterAddingNodes, mapData.indexObservable));
 81.3480 +
 81.3481 +            // Put nodes in the right place if they aren't there already
 81.3482 +            for (var j = 0; node = mapData.mappedNodes[j]; nextNode = node.nextSibling, lastNode = node, j++) {
 81.3483 +                if (node !== nextNode)
 81.3484 +                    ko.virtualElements.insertAfter(domNode, node, lastNode);
 81.3485 +            }
 81.3486 +
 81.3487 +            // Run the callbacks for newly added nodes (for example, to apply bindings, etc.)
 81.3488 +            if (!mapData.initialized && callbackAfterAddingNodes) {
 81.3489 +                callbackAfterAddingNodes(mapData.arrayEntry, mapData.mappedNodes, mapData.indexObservable);
 81.3490 +                mapData.initialized = true;
 81.3491 +            }
 81.3492 +        }
 81.3493 +
 81.3494 +        // If there's a beforeRemove callback, call it after reordering.
 81.3495 +        // Note that we assume that the beforeRemove callback will usually be used to remove the nodes using
 81.3496 +        // some sort of animation, which is why we first reorder the nodes that will be removed. If the
 81.3497 +        // callback instead removes the nodes right away, it would be more efficient to skip reordering them.
 81.3498 +        // Perhaps we'll make that change in the future if this scenario becomes more common.
 81.3499 +        callCallback(options['beforeRemove'], itemsForBeforeRemoveCallbacks);
 81.3500 +
 81.3501 +        // Finally call afterMove and afterAdd callbacks
 81.3502 +        callCallback(options['afterMove'], itemsForMoveCallbacks);
 81.3503 +        callCallback(options['afterAdd'], itemsForAfterAddCallbacks);
 81.3504 +
 81.3505 +        // Store a copy of the array items we just considered so we can difference it next time
 81.3506 +        ko.utils.domData.set(domNode, lastMappingResultDomDataKey, newMappingResult);
 81.3507 +    }
 81.3508 +})();
 81.3509 +
 81.3510 +ko.exportSymbol('utils.setDomNodeChildrenFromArrayMapping', ko.utils.setDomNodeChildrenFromArrayMapping);
 81.3511 +ko.nativeTemplateEngine = function () {
 81.3512 +    this['allowTemplateRewriting'] = false;
 81.3513 +}
 81.3514 +
 81.3515 +ko.nativeTemplateEngine.prototype = new ko.templateEngine();
 81.3516 +ko.nativeTemplateEngine.prototype['renderTemplateSource'] = function (templateSource, bindingContext, options) {
 81.3517 +    var useNodesIfAvailable = !(ko.utils.ieVersion < 9), // IE<9 cloneNode doesn't work properly
 81.3518 +        templateNodesFunc = useNodesIfAvailable ? templateSource['nodes'] : null,
 81.3519 +        templateNodes = templateNodesFunc ? templateSource['nodes']() : null;
 81.3520 +
 81.3521 +    if (templateNodes) {
 81.3522 +        return ko.utils.makeArray(templateNodes.cloneNode(true).childNodes);
 81.3523 +    } else {
 81.3524 +        var templateText = templateSource['text']();
 81.3525 +        return ko.utils.parseHtmlFragment(templateText);
 81.3526 +    }
 81.3527 +};
 81.3528 +
 81.3529 +ko.nativeTemplateEngine.instance = new ko.nativeTemplateEngine();
 81.3530 +ko.setTemplateEngine(ko.nativeTemplateEngine.instance);
 81.3531 +
 81.3532 +ko.exportSymbol('nativeTemplateEngine', ko.nativeTemplateEngine);
 81.3533 +(function() {
 81.3534 +    ko.jqueryTmplTemplateEngine = function () {
 81.3535 +        // Detect which version of jquery-tmpl you're using. Unfortunately jquery-tmpl
 81.3536 +        // doesn't expose a version number, so we have to infer it.
 81.3537 +        // Note that as of Knockout 1.3, we only support jQuery.tmpl 1.0.0pre and later,
 81.3538 +        // which KO internally refers to as version "2", so older versions are no longer detected.
 81.3539 +        var jQueryTmplVersion = this.jQueryTmplVersion = (function() {
 81.3540 +            if ((typeof(jQuery) == "undefined") || !(jQuery['tmpl']))
 81.3541 +                return 0;
 81.3542 +            // Since it exposes no official version number, we use our own numbering system. To be updated as jquery-tmpl evolves.
 81.3543 +            try {
 81.3544 +                if (jQuery['tmpl']['tag']['tmpl']['open'].toString().indexOf('__') >= 0) {
 81.3545 +                    // Since 1.0.0pre, custom tags should append markup to an array called "__"
 81.3546 +                    return 2; // Final version of jquery.tmpl
 81.3547 +                }
 81.3548 +            } catch(ex) { /* Apparently not the version we were looking for */ }
 81.3549 +
 81.3550 +            return 1; // Any older version that we don't support
 81.3551 +        })();
 81.3552 +
 81.3553 +        function ensureHasReferencedJQueryTemplates() {
 81.3554 +            if (jQueryTmplVersion < 2)
 81.3555 +                throw new Error("Your version of jQuery.tmpl is too old. Please upgrade to jQuery.tmpl 1.0.0pre or later.");
 81.3556 +        }
 81.3557 +
 81.3558 +        function executeTemplate(compiledTemplate, data, jQueryTemplateOptions) {
 81.3559 +            return jQuery['tmpl'](compiledTemplate, data, jQueryTemplateOptions);
 81.3560 +        }
 81.3561 +
 81.3562 +        this['renderTemplateSource'] = function(templateSource, bindingContext, options) {
 81.3563 +            options = options || {};
 81.3564 +            ensureHasReferencedJQueryTemplates();
 81.3565 +
 81.3566 +            // Ensure we have stored a precompiled version of this template (don't want to reparse on every render)
 81.3567 +            var precompiled = templateSource['data']('precompiled');
 81.3568 +            if (!precompiled) {
 81.3569 +                var templateText = templateSource['text']() || "";
 81.3570 +                // Wrap in "with($whatever.koBindingContext) { ... }"
 81.3571 +                templateText = "{{ko_with $item.koBindingContext}}" + templateText + "{{/ko_with}}";
 81.3572 +
 81.3573 +                precompiled = jQuery['template'](null, templateText);
 81.3574 +                templateSource['data']('precompiled', precompiled);
 81.3575 +            }
 81.3576 +
 81.3577 +            var data = [bindingContext['$data']]; // Prewrap the data in an array to stop jquery.tmpl from trying to unwrap any arrays
 81.3578 +            var jQueryTemplateOptions = jQuery['extend']({ 'koBindingContext': bindingContext }, options['templateOptions']);
 81.3579 +
 81.3580 +            var resultNodes = executeTemplate(precompiled, data, jQueryTemplateOptions);
 81.3581 +            resultNodes['appendTo'](document.createElement("div")); // Using "appendTo" forces jQuery/jQuery.tmpl to perform necessary cleanup work
 81.3582 +
 81.3583 +            jQuery['fragments'] = {}; // Clear jQuery's fragment cache to avoid a memory leak after a large number of template renders
 81.3584 +            return resultNodes;
 81.3585 +        };
 81.3586 +
 81.3587 +        this['createJavaScriptEvaluatorBlock'] = function(script) {
 81.3588 +            return "{{ko_code ((function() { return " + script + " })()) }}";
 81.3589 +        };
 81.3590 +
 81.3591 +        this['addTemplate'] = function(templateName, templateMarkup) {
 81.3592 +            document.write("<script type='text/html' id='" + templateName + "'>" + templateMarkup + "</script>");
 81.3593 +        };
 81.3594 +
 81.3595 +        if (jQueryTmplVersion > 0) {
 81.3596 +            jQuery['tmpl']['tag']['ko_code'] = {
 81.3597 +                open: "__.push($1 || '');"
 81.3598 +            };
 81.3599 +            jQuery['tmpl']['tag']['ko_with'] = {
 81.3600 +                open: "with($1) {",
 81.3601 +                close: "} "
 81.3602 +            };
 81.3603 +        }
 81.3604 +    };
 81.3605 +
 81.3606 +    ko.jqueryTmplTemplateEngine.prototype = new ko.templateEngine();
 81.3607 +
 81.3608 +    // Use this one by default *only if jquery.tmpl is referenced*
 81.3609 +    var jqueryTmplTemplateEngineInstance = new ko.jqueryTmplTemplateEngine();
 81.3610 +    if (jqueryTmplTemplateEngineInstance.jQueryTmplVersion > 0)
 81.3611 +        ko.setTemplateEngine(jqueryTmplTemplateEngineInstance);
 81.3612 +
 81.3613 +    ko.exportSymbol('jqueryTmplTemplateEngine', ko.jqueryTmplTemplateEngine);
 81.3614 +})();
 81.3615 +});
 81.3616 +})(window,document,navigator,window["jQuery"]);
 81.3617 +})();
 81.3618 \ No newline at end of file
    82.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    82.2 +++ b/ko/bck2brwsr/src/test/java/org/apidesign/bck2brwsr/ko2brwsr/Bck2BrwsrKnockoutTest.java	Mon Oct 07 14:20:58 2013 +0200
    82.3 @@ -0,0 +1,120 @@
    82.4 +/**
    82.5 + * Back 2 Browser Bytecode Translator
    82.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    82.7 + *
    82.8 + * This program is free software: you can redistribute it and/or modify
    82.9 + * it under the terms of the GNU General Public License as published by
   82.10 + * the Free Software Foundation, version 2 of the License.
   82.11 + *
   82.12 + * This program is distributed in the hope that it will be useful,
   82.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   82.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   82.15 + * GNU General Public License for more details.
   82.16 + *
   82.17 + * You should have received a copy of the GNU General Public License
   82.18 + * along with this program. Look for COPYING file in the top folder.
   82.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   82.20 + */
   82.21 +package org.apidesign.bck2brwsr.ko2brwsr;
   82.22 +
   82.23 +import java.io.IOException;
   82.24 +import java.net.URI;
   82.25 +import java.net.URISyntaxException;
   82.26 +import java.net.URL;
   82.27 +import java.util.Map;
   82.28 +import net.java.html.BrwsrCtx;
   82.29 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   82.30 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   82.31 +import org.apidesign.html.context.spi.Contexts;
   82.32 +import org.apidesign.html.json.spi.Technology;
   82.33 +import org.apidesign.html.json.spi.Transfer;
   82.34 +import org.apidesign.html.json.spi.WSTransfer;
   82.35 +import org.apidesign.html.json.tck.KOTest;
   82.36 +import org.apidesign.html.json.tck.KnockoutTCK;
   82.37 +import org.openide.util.lookup.ServiceProvider;
   82.38 +import org.testng.annotations.Factory;
   82.39 +
   82.40 +/**
   82.41 + *
   82.42 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   82.43 + */
   82.44 +@ServiceProvider(service = KnockoutTCK.class)
   82.45 +public final class Bck2BrwsrKnockoutTest extends KnockoutTCK {
   82.46 +    @Factory public static Object[] create() {
   82.47 +        return VMTest.newTests().
   82.48 +            withClasses(testClasses()).
   82.49 +            withLaunchers("bck2brwsr").
   82.50 +            withTestAnnotation(KOTest.class).
   82.51 +            build();
   82.52 +    }
   82.53 +    
   82.54 +    @Override
   82.55 +    public BrwsrCtx createContext() {
   82.56 +        return Contexts.newBuilder().
   82.57 +            register(Transfer.class, BrwsrCtxImpl.DEFAULT, 9).
   82.58 +            register(WSTransfer.class, BrwsrCtxImpl.DEFAULT, 9).
   82.59 +            register(Technology.class, BrwsrCtxImpl.DEFAULT, 9).build();
   82.60 +    }
   82.61 +
   82.62 +
   82.63 +    
   82.64 +    @Override
   82.65 +    public Object createJSON(Map<String, Object> values) {
   82.66 +        Object json = createJSON();
   82.67 +        
   82.68 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
   82.69 +            putValue(json, entry.getKey(), entry.getValue());
   82.70 +        }
   82.71 +        return json;
   82.72 +    }
   82.73 +
   82.74 +    @JavaScriptBody(args = {}, body = "return new Object();")
   82.75 +    private static native Object createJSON();
   82.76 +
   82.77 +    @JavaScriptBody(args = { "json", "key", "value" }, body = "json[key] = value;")
   82.78 +    private static native void putValue(Object json, String key, Object value);
   82.79 +
   82.80 +    @Override
   82.81 +    public Object executeScript(String script, Object[] arguments) {
   82.82 +        return execScript(script, arguments);
   82.83 +    }
   82.84 +    
   82.85 +    @JavaScriptBody(args = { "s", "args" }, body = 
   82.86 +        "var f = new Function(s); return f.apply(null, args);"
   82.87 +    )
   82.88 +    private static native Object execScript(String s, Object[] arguments);
   82.89 +    
   82.90 +    @JavaScriptBody(args = {  }, body = 
   82.91 +          "var h;"
   82.92 +        + "if (!!window && !!window.location && !!window.location.href)\n"
   82.93 +        + "  h = window.location.href;\n"
   82.94 +        + "else "
   82.95 +        + "  h = null;"
   82.96 +        + "return h;\n"
   82.97 +    )
   82.98 +    private static native String findBaseURL();
   82.99 +    
  82.100 +    @Override
  82.101 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
  82.102 +        try {
  82.103 +            final URL baseURL = new URL(findBaseURL());
  82.104 +            StringBuilder sb = new StringBuilder();
  82.105 +            sb.append("/dynamic?mimeType=").append(mimeType);
  82.106 +            for (int i = 0; i < parameters.length; i++) {
  82.107 +                sb.append("&param" + i).append("=").append(parameters[i]);
  82.108 +            }
  82.109 +            String mangle = content.replace("\n", "%0a")
  82.110 +                .replace("\"", "\\\"").replace(" ", "%20");
  82.111 +            sb.append("&content=").append(mangle);
  82.112 +
  82.113 +            URL query = new URL(baseURL, sb.toString());
  82.114 +            String uri = (String) query.getContent(new Class[] { String.class });
  82.115 +            URI connectTo = new URI(uri.trim());
  82.116 +            return connectTo;
  82.117 +        } catch (IOException ex) {
  82.118 +            throw new IllegalStateException(ex);
  82.119 +        } catch (URISyntaxException ex) {
  82.120 +            throw new IllegalStateException(ex);
  82.121 +        }
  82.122 +    }    
  82.123 +}
    83.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    83.2 +++ b/ko/fx/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    83.3 @@ -0,0 +1,119 @@
    83.4 +<?xml version="1.0"?>
    83.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    83.6 +  <modelVersion>4.0.0</modelVersion>
    83.7 +  <parent>
    83.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    83.9 +    <artifactId>ko</artifactId>
   83.10 +    <version>0.9-SNAPSHOT</version>
   83.11 +  </parent>
   83.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   83.13 +  <artifactId>ko-fx</artifactId>
   83.14 +  <version>0.9-SNAPSHOT</version>
   83.15 +  <name>Knockout.fx in Brwsr</name>
   83.16 +  <url>http://maven.apache.org</url>
   83.17 +  <properties>
   83.18 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   83.19 +  </properties>
   83.20 +  <build>
   83.21 +      <plugins>
   83.22 +          <plugin>
   83.23 +              <groupId>org.apache.maven.plugins</groupId>
   83.24 +              <artifactId>maven-javadoc-plugin</artifactId>
   83.25 +              <configuration>
   83.26 +                  <skip>false</skip>
   83.27 +              </configuration>
   83.28 +          </plugin>
   83.29 +      </plugins>
   83.30 +  </build>
   83.31 +  <dependencies>
   83.32 +    <dependency>
   83.33 +        <groupId>com.oracle</groupId>
   83.34 +        <artifactId>javafx</artifactId>
   83.35 +        <version>2.2</version>
   83.36 +        <scope>system</scope>
   83.37 +        <systemPath>${jfxrt.jar}</systemPath>
   83.38 +    </dependency>
   83.39 +    <dependency>
   83.40 +      <groupId>org.json</groupId>
   83.41 +      <artifactId>json</artifactId>
   83.42 +      <version>20090211</version>
   83.43 +      <type>jar</type>
   83.44 +    </dependency>
   83.45 +    <dependency>
   83.46 +      <groupId>org.apidesign.html</groupId>
   83.47 +      <artifactId>net.java.html.json</artifactId>
   83.48 +      <version>${net.java.html.version}</version>
   83.49 +    </dependency>
   83.50 +    <dependency>
   83.51 +      <groupId>org.testng</groupId>
   83.52 +      <artifactId>testng</artifactId>
   83.53 +      <scope>test</scope>
   83.54 +    </dependency>
   83.55 +    <dependency>
   83.56 +      <groupId>org.apidesign.html</groupId>
   83.57 +      <artifactId>net.java.html.json.tck</artifactId>
   83.58 +      <version>${net.java.html.version}</version>
   83.59 +      <scope>test</scope>
   83.60 +    </dependency>
   83.61 +    <dependency>
   83.62 +      <groupId>org.netbeans.api</groupId>
   83.63 +      <artifactId>org-openide-util</artifactId>
   83.64 +      <scope>provided</scope>
   83.65 +    </dependency>
   83.66 +    <dependency>
   83.67 +      <groupId>org.apidesign.bck2brwsr</groupId>
   83.68 +      <artifactId>launcher.fx</artifactId>
   83.69 +      <version>${project.version}</version>
   83.70 +      <scope>test</scope>
   83.71 +    </dependency>
   83.72 +    <dependency>
   83.73 +      <groupId>org.apidesign.html</groupId>
   83.74 +      <artifactId>net.java.html.boot</artifactId>
   83.75 +      <version>${net.java.html.version}</version>
   83.76 +      <type>jar</type>
   83.77 +    </dependency>
   83.78 +    <dependency>
   83.79 +      <groupId>org.apidesign.html</groupId>
   83.80 +      <artifactId>ko-fx</artifactId>
   83.81 +      <version>${net.java.html.version}</version>
   83.82 +      <type>jar</type>
   83.83 +    </dependency>
   83.84 +    <dependency>
   83.85 +      <groupId>org.apidesign.bck2brwsr</groupId>
   83.86 +      <artifactId>vmtest</artifactId>
   83.87 +      <version>${project.version}</version>
   83.88 +      <scope>test</scope>
   83.89 +      <type>jar</type>
   83.90 +    </dependency>
   83.91 +    <dependency>
   83.92 +      <groupId>org.apidesign.html</groupId>
   83.93 +      <artifactId>ko-ws-tyrus</artifactId>
   83.94 +      <version>${net.java.html.version}</version>
   83.95 +      <scope>test</scope>
   83.96 +    </dependency>
   83.97 +  </dependencies>
   83.98 +  <profiles>
   83.99 +      <profile>
  83.100 +          <id>jdk8</id>
  83.101 +          <activation>
  83.102 +              <file>
  83.103 +                  <exists>${java.home}/lib/ext/jfxrt.jar</exists>
  83.104 +              </file>
  83.105 +          </activation>
  83.106 +          <properties>
  83.107 +            <jfxrt.jar>${java.home}/lib/ext/jfxrt.jar</jfxrt.jar>
  83.108 +          </properties>
  83.109 +      </profile>
  83.110 +      <profile>
  83.111 +          <id>jdk7</id>
  83.112 +          <activation>
  83.113 +              <file>
  83.114 +                  <exists>${java.home}/lib/jfxrt.jar</exists>
  83.115 +              </file>
  83.116 +          </activation>
  83.117 +          <properties>
  83.118 +            <jfxrt.jar>${java.home}/lib/jfxrt.jar</jfxrt.jar>
  83.119 +          </properties>
  83.120 +      </profile>
  83.121 +  </profiles>
  83.122 +</project>
    84.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    84.2 +++ b/ko/fx/src/test/java/org/apidesign/bck2brwsr/kofx/KnockoutFXTest.java	Mon Oct 07 14:20:58 2013 +0200
    84.3 @@ -0,0 +1,133 @@
    84.4 +/**
    84.5 + * Back 2 Browser Bytecode Translator
    84.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    84.7 + *
    84.8 + * This program is free software: you can redistribute it and/or modify
    84.9 + * it under the terms of the GNU General Public License as published by
   84.10 + * the Free Software Foundation, version 2 of the License.
   84.11 + *
   84.12 + * This program is distributed in the hope that it will be useful,
   84.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   84.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   84.15 + * GNU General Public License for more details.
   84.16 + *
   84.17 + * You should have received a copy of the GNU General Public License
   84.18 + * along with this program. Look for COPYING file in the top folder.
   84.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   84.20 + */
   84.21 +package org.apidesign.bck2brwsr.kofx;
   84.22 +
   84.23 +import java.io.BufferedReader;
   84.24 +import java.io.IOException;
   84.25 +import java.io.InputStreamReader;
   84.26 +import java.net.URI;
   84.27 +import java.net.URISyntaxException;
   84.28 +import java.net.URL;
   84.29 +import java.net.URLConnection;
   84.30 +import java.util.Map;
   84.31 +import net.java.html.BrwsrCtx;
   84.32 +import net.java.html.js.JavaScriptBody;
   84.33 +import org.apidesign.bck2brwsr.vmtest.VMTest;
   84.34 +import org.apidesign.html.boot.impl.FnUtils;
   84.35 +import org.apidesign.html.context.spi.Contexts;
   84.36 +import org.apidesign.html.json.spi.Technology;
   84.37 +import org.apidesign.html.json.spi.Transfer;
   84.38 +import org.apidesign.html.json.spi.WSTransfer;
   84.39 +import org.apidesign.html.json.tck.KOTest;
   84.40 +import org.apidesign.html.json.tck.KnockoutTCK;
   84.41 +import org.apidesign.html.kofx.FXContext;
   84.42 +import org.apidesign.html.wstyrus.TyrusContext;
   84.43 +import org.json.JSONException;
   84.44 +import org.json.JSONObject;
   84.45 +import org.openide.util.lookup.ServiceProvider;
   84.46 +import org.testng.annotations.Factory;
   84.47 +
   84.48 +/**
   84.49 + *
   84.50 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   84.51 + */
   84.52 +@ServiceProvider(service = KnockoutTCK.class)
   84.53 +public final class KnockoutFXTest extends KnockoutTCK {
   84.54 +    public KnockoutFXTest() {
   84.55 +    }
   84.56 +
   84.57 +    @Factory public static Object[] compatibilityTests() {
   84.58 +        return VMTest.newTests().
   84.59 +            withClasses(testClasses()).
   84.60 +            withTestAnnotation(KOTest.class).
   84.61 +            withLaunchers("fxbrwsr").build();
   84.62 +    }
   84.63 +
   84.64 +    @Override
   84.65 +    public BrwsrCtx createContext() {
   84.66 +        FXContext fx = new FXContext(FnUtils.currentPresenter());
   84.67 +        TyrusContext tc = new TyrusContext();
   84.68 +        Contexts.Builder b = Contexts.newBuilder().
   84.69 +            register(Technology.class, fx, 10).
   84.70 +            register(Transfer.class, fx, 10);
   84.71 +        try {
   84.72 +            Class.forName("java.util.function.Function");
   84.73 +            // prefer WebView's WebSockets on JDK8
   84.74 +            b.register(WSTransfer.class, fx, 10);
   84.75 +        } catch (ClassNotFoundException ex) {
   84.76 +            // ok, JDK7 needs tyrus
   84.77 +            b.register(WSTransfer.class, tc, 20);
   84.78 +        }
   84.79 +        return b.build();
   84.80 +    }
   84.81 +
   84.82 +    @Override
   84.83 +    public Object createJSON(Map<String, Object> values) {
   84.84 +        JSONObject json = new JSONObject();
   84.85 +        for (Map.Entry<String, Object> entry : values.entrySet()) {
   84.86 +            try {
   84.87 +                json.put(entry.getKey(), entry.getValue());
   84.88 +            } catch (JSONException ex) {
   84.89 +                throw new IllegalStateException(ex);
   84.90 +            }
   84.91 +        }
   84.92 +        return json;
   84.93 +    }
   84.94 +
   84.95 +    @Override
   84.96 +    @JavaScriptBody(args = { "s", "args" }, body = ""
   84.97 +        + "var f = new Function(s); "
   84.98 +        + "return f.apply(null, args);"
   84.99 +    )
  84.100 +    public native Object executeScript(String script, Object[] arguments);
  84.101 +
  84.102 +    @JavaScriptBody(args = {  }, body = 
  84.103 +          "var h;"
  84.104 +        + "if (!!window && !!window.location && !!window.location.href)\n"
  84.105 +        + "  h = window.location.href;\n"
  84.106 +        + "else "
  84.107 +        + "  h = null;"
  84.108 +        + "return h;\n"
  84.109 +    )
  84.110 +    private static native String findBaseURL();
  84.111 +    
  84.112 +    @Override
  84.113 +    public URI prepareURL(String content, String mimeType, String[] parameters) {
  84.114 +        try {
  84.115 +            final URL baseURL = new URL(findBaseURL());
  84.116 +            StringBuilder sb = new StringBuilder();
  84.117 +            sb.append("/dynamic?mimeType=").append(mimeType);
  84.118 +            for (int i = 0; i < parameters.length; i++) {
  84.119 +                sb.append("&param" + i).append("=").append(parameters[i]);
  84.120 +            }
  84.121 +            String mangle = content.replace("\n", "%0a")
  84.122 +                .replace("\"", "\\\"").replace(" ", "%20");
  84.123 +            sb.append("&content=").append(mangle);
  84.124 +
  84.125 +            URL query = new URL(baseURL, sb.toString());
  84.126 +            URLConnection c = query.openConnection();
  84.127 +            BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
  84.128 +            URI connectTo = new URI(br.readLine());
  84.129 +            return connectTo;
  84.130 +        } catch (IOException ex) {
  84.131 +            throw new IllegalStateException(ex);
  84.132 +        } catch (URISyntaxException ex) {
  84.133 +            throw new IllegalStateException(ex);
  84.134 +        }
  84.135 +    }
  84.136 +}
    85.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    85.2 +++ b/ko/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    85.3 @@ -0,0 +1,20 @@
    85.4 +<?xml version="1.0" encoding="UTF-8"?>
    85.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    85.6 +  <modelVersion>4.0.0</modelVersion>
    85.7 +  <groupId>org.apidesign.bck2brwsr</groupId>
    85.8 +  <artifactId>ko</artifactId>
    85.9 +  <version>0.9-SNAPSHOT</version>
   85.10 +  <packaging>pom</packaging>
   85.11 +  <name>Bck2Brwsr Knockout Support</name>
   85.12 +  <parent>
   85.13 +    <groupId>org.apidesign</groupId>
   85.14 +    <artifactId>bck2brwsr</artifactId>
   85.15 +    <version>0.9-SNAPSHOT</version>
   85.16 +  </parent>  
   85.17 +  <modules>
   85.18 +    <module>archetype</module>
   85.19 +    <module>archetype-test</module>
   85.20 +    <module>bck2brwsr</module>
   85.21 +    <module>fx</module>
   85.22 +  </modules>
   85.23 +</project>
    86.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    86.2 +++ b/launcher/api/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    86.3 @@ -0,0 +1,31 @@
    86.4 +<?xml version="1.0"?>
    86.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    86.6 +  <modelVersion>4.0.0</modelVersion>
    86.7 +  <parent>
    86.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    86.9 +    <artifactId>launcher-pom</artifactId>
   86.10 +    <version>0.9-SNAPSHOT</version>
   86.11 +  </parent>
   86.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   86.13 +  <artifactId>launcher</artifactId>
   86.14 +  <version>0.9-SNAPSHOT</version>
   86.15 +  <name>Launcher API</name>
   86.16 +  <url>http://maven.apache.org</url>
   86.17 +  <properties>
   86.18 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   86.19 +  </properties>
   86.20 +    <build>
   86.21 +        <plugins>
   86.22 +            <plugin>
   86.23 +                <groupId>org.apache.maven.plugins</groupId>
   86.24 +                <artifactId>maven-javadoc-plugin</artifactId>
   86.25 +                <configuration>
   86.26 +                    <subpackages>org.apidesign.bck2brwsr.launcher</subpackages>
   86.27 +                    <skip>false</skip>
   86.28 +                </configuration>
   86.29 +            </plugin>
   86.30 +        </plugins>
   86.31 +    </build>
   86.32 +  <dependencies>
   86.33 +  </dependencies>
   86.34 +</project>
    87.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    87.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Mon Oct 07 14:20:58 2013 +0200
    87.3 @@ -0,0 +1,115 @@
    87.4 +/**
    87.5 + * Back 2 Browser Bytecode Translator
    87.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    87.7 + *
    87.8 + * This program is free software: you can redistribute it and/or modify
    87.9 + * it under the terms of the GNU General Public License as published by
   87.10 + * the Free Software Foundation, version 2 of the License.
   87.11 + *
   87.12 + * This program is distributed in the hope that it will be useful,
   87.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   87.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   87.15 + * GNU General Public License for more details.
   87.16 + *
   87.17 + * You should have received a copy of the GNU General Public License
   87.18 + * along with this program. Look for COPYING file in the top folder.
   87.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   87.20 + */
   87.21 +package org.apidesign.bck2brwsr.launcher;
   87.22 +
   87.23 +import java.io.IOException;
   87.24 +import java.io.InputStream;
   87.25 +import java.net.URI;
   87.26 +import java.util.ArrayList;
   87.27 +import java.util.List;
   87.28 +import java.util.concurrent.CountDownLatch;
   87.29 +import java.util.concurrent.TimeUnit;
   87.30 +
   87.31 +/** Represents individual method invocation, its context and its result.
   87.32 + *
   87.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   87.34 + */
   87.35 +public final class InvocationContext {
   87.36 +    final CountDownLatch wait = new CountDownLatch(1);
   87.37 +    final Class<?> clazz;
   87.38 +    final String methodName;
   87.39 +    private final Launcher launcher;
   87.40 +    private String result;
   87.41 +    private Throwable exception;
   87.42 +    String html;
   87.43 +    final List<Resource> resources = new ArrayList<>();
   87.44 +
   87.45 +    InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
   87.46 +        this.launcher = launcher;
   87.47 +        this.clazz = clazz;
   87.48 +        this.methodName = methodName;
   87.49 +    }
   87.50 +    
   87.51 +    /** An HTML fragment to be available for the execution. Useful primarily when
   87.52 +     * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
   87.53 +     * @param html the html fragment
   87.54 +     */
   87.55 +    public void setHtmlFragment(String html) {
   87.56 +        this.html = html;
   87.57 +    }
   87.58 +    
   87.59 +    /** HTTP resource to be available during execution. An invocation may
   87.60 +     * perform an HTTP query and obtain a resource relative to the page.
   87.61 +     */
   87.62 +    public void addHttpResource(String relativePath, String mimeType, String[] parameters, InputStream content) {
   87.63 +        if (relativePath == null || mimeType == null || content == null || parameters == null) {
   87.64 +            throw new NullPointerException();
   87.65 +        }
   87.66 +        resources.add(new Resource(content, mimeType, relativePath, parameters));
   87.67 +    }
   87.68 +    
   87.69 +    /** Invokes the associated method. 
   87.70 +     * @return the textual result of the invocation
   87.71 +     */
   87.72 +    public String invoke() throws IOException {
   87.73 +        launcher.runMethod(this);
   87.74 +        return toString();
   87.75 +    }
   87.76 +    
   87.77 +    /** Obtains textual result of the invocation.
   87.78 +     * @return text representing the exception or result value
   87.79 +     */
   87.80 +    @Override
   87.81 +    public String toString() {
   87.82 +        if (exception != null) {
   87.83 +            return exception.toString();
   87.84 +        }
   87.85 +        return result;
   87.86 +    }
   87.87 +    
   87.88 +    /**
   87.89 +     * @param timeOut
   87.90 +     * @throws InterruptedException 
   87.91 +     */
   87.92 +    void await(long timeOut) throws InterruptedException {
   87.93 +        wait.await(timeOut, TimeUnit.MILLISECONDS);
   87.94 +    }
   87.95 +    
   87.96 +    void result(String r, Throwable e) {
   87.97 +        this.result = r;
   87.98 +        this.exception = e;
   87.99 +        wait.countDown();
  87.100 +    }
  87.101 +
  87.102 +    static final class Resource {
  87.103 +        final InputStream httpContent;
  87.104 +        final String httpType;
  87.105 +        final String httpPath;
  87.106 +        final String[] parameters;
  87.107 +
  87.108 +        Resource(InputStream httpContent, String httpType, String httpPath,
  87.109 +            String[] parameters
  87.110 +        ) {
  87.111 +            httpContent.mark(Integer.MAX_VALUE);
  87.112 +            this.httpContent = httpContent;
  87.113 +            this.httpType = httpType;
  87.114 +            this.httpPath = httpPath;
  87.115 +            this.parameters = parameters;
  87.116 +        }
  87.117 +    }
  87.118 +}
    88.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    88.2 +++ b/launcher/api/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Mon Oct 07 14:20:58 2013 +0200
    88.3 @@ -0,0 +1,186 @@
    88.4 +/**
    88.5 + * Back 2 Browser Bytecode Translator
    88.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    88.7 + *
    88.8 + * This program is free software: you can redistribute it and/or modify
    88.9 + * it under the terms of the GNU General Public License as published by
   88.10 + * the Free Software Foundation, version 2 of the License.
   88.11 + *
   88.12 + * This program is distributed in the hope that it will be useful,
   88.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   88.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   88.15 + * GNU General Public License for more details.
   88.16 + *
   88.17 + * You should have received a copy of the GNU General Public License
   88.18 + * along with this program. Look for COPYING file in the top folder.
   88.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   88.20 + */
   88.21 +package org.apidesign.bck2brwsr.launcher;
   88.22 +
   88.23 +import java.io.Closeable;
   88.24 +import java.io.File;
   88.25 +import java.io.IOException;
   88.26 +import java.lang.reflect.Constructor;
   88.27 +
   88.28 +/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
   88.29 + * Either in {@link Launcher#createJavaScript JavaScript engine}, 
   88.30 + * or in {@link Launcher#createBrowser external browser}.
   88.31 + * <p>
   88.32 + * There also are methods to {@link #showDir(java.io.File, java.lang.String) display pages} 
   88.33 + * in an external browser served by internal HTTP server.
   88.34 + *
   88.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   88.36 + */
   88.37 +public abstract class Launcher {
   88.38 +
   88.39 +    Launcher() {
   88.40 +    }
   88.41 +
   88.42 +    /** Initializes the launcher. This may mean starting a web browser or
   88.43 +     * initializing execution engine.
   88.44 +     * @throws IOException if something goes wrong
   88.45 +     */
   88.46 +    public abstract void initialize() throws IOException;
   88.47 +    
   88.48 +    /** Shuts down the launcher.
   88.49 +     * @throws IOException if something goes wrong
   88.50 +     */
   88.51 +    public abstract void shutdown() throws IOException;
   88.52 +    
   88.53 +    
   88.54 +    /** Builds an invocation context. The context can later be customized
   88.55 +     * and {@link InvocationContext#invoke() invoked}.
   88.56 +     * 
   88.57 +     * @param clazz the class to execute method from
   88.58 +     * @param method the method to execute
   88.59 +     * @return the context pointing to the selected method
   88.60 +     */
   88.61 +    public InvocationContext createInvocation(Class<?> clazz, String method) {
   88.62 +        return new InvocationContext(this, clazz, method);
   88.63 +    }
   88.64 +    
   88.65 +
   88.66 +    /** Creates launcher that uses internal JavaScript engine (Rhino).
   88.67 +     * @return the launcher
   88.68 +     */
   88.69 +    public static Launcher createJavaScript() {
   88.70 +        try {
   88.71 +            Class<?> c = loadClass("org.apidesign.bck2brwsr.launcher.JSLauncher");
   88.72 +            return (Launcher) c.newInstance();
   88.73 +        } catch (Exception ex) {
   88.74 +            throw new IllegalStateException("Please include org.apidesign.bck2brwsr:launcher.html dependency!", ex);
   88.75 +        }
   88.76 +    }
   88.77 +    
   88.78 +    /** Creates launcher that is using external browser.
   88.79 +     * 
   88.80 +     * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
   88.81 +     *    or a string to execute in an external process (with a parameter to the URL)
   88.82 +     * @return launcher executing in external browser.
   88.83 +     */
   88.84 +    public static Launcher createBrowser(String cmd) {
   88.85 +        String msg = "Trying to create browser '" + cmd + "'";
   88.86 +        try {
   88.87 +            Class<?> c;
   88.88 +            if ("fxbrwsr".equals(cmd)) { // NOI18N
   88.89 +                msg = "Please include org.apidesign.bck2brwsr:launcher.fx dependency!";
   88.90 +                c = loadClass("org.apidesign.bck2brwsr.launcher.FXBrwsrLauncher"); // NOI18N
   88.91 +            } else {
   88.92 +                msg = "Please include org.apidesign.bck2brwsr:launcher.html dependency!";
   88.93 +                c = loadClass("org.apidesign.bck2brwsr.launcher.Bck2BrwsrLauncher"); // NOI18N
   88.94 +                if ("bck2brwsr".equals(cmd)) { // NOI18N
   88.95 +                    // use default executable
   88.96 +                    cmd = null;
   88.97 +                }
   88.98 +            }
   88.99 +            Constructor<?> cnstr = c.getConstructor(String.class);
  88.100 +            return (Launcher) cnstr.newInstance(cmd);
  88.101 +        } catch (Exception ex) {
  88.102 +            throw new IllegalStateException(msg, ex);
  88.103 +        }
  88.104 +    }
  88.105 +    
  88.106 +    /** Starts an HTTP server which provides access to classes and resources
  88.107 +     * available in the <code>classes</code> URL and shows a start page
  88.108 +     * available as {@link ClassLoader#getResource(java.lang.String)} from the
  88.109 +     * provide classloader. Opens a browser with URL showing the start page.
  88.110 +     * 
  88.111 +     * @param classes classloader offering access to classes and resources
  88.112 +     * @param startpage page to show in the browser
  88.113 +     * @return interface that allows one to stop the server
  88.114 +     * @throws IOException if something goes wrong
  88.115 +     */
  88.116 +    public static Closeable showURL(ClassLoader classes, String startpage) throws IOException {
  88.117 +        return showURL(null, classes, startpage);
  88.118 +    }
  88.119 +    /** Starts an HTTP server which provides access to classes and resources
  88.120 +     * available in the <code>classes</code> URL and shows a start page
  88.121 +     * available as {@link ClassLoader#getResource(java.lang.String)} from the
  88.122 +     * provide classloader. Opens a browser with URL showing the start page.
  88.123 +     * 
  88.124 +     * @param brwsr name of browser to use or <code>null</code>
  88.125 +     * @param classes classloader offering access to classes and resources
  88.126 +     * @param startpage page to show in the browser
  88.127 +     * @return interface that allows one to stop the server
  88.128 +     * @throws IOException if something goes wrong
  88.129 +     * @since 0.7
  88.130 +     */
  88.131 +    public static Closeable showURL(String brwsr, ClassLoader classes, String startpage) throws IOException {
  88.132 +        Launcher l = createBrowser(brwsr);
  88.133 +        l.addClassLoader(classes);
  88.134 +        l.showURL(startpage);
  88.135 +        return (Closeable) l;
  88.136 +    }
  88.137 +    /** Starts an HTTP server which provides access to certain directory.
  88.138 +     * The <code>startpage</code> should be relative location inside the root 
  88.139 +     * directory. Opens a browser with URL showing the start page.
  88.140 +     * 
  88.141 +     * @param brwsr type of the browser to use
  88.142 +     * @param directory the root directory on disk
  88.143 +     * @param classes additional classloader with access to classes or <code>null</code>
  88.144 +     * @param startpage relative path from the root to the page
  88.145 +     * @return instance of server that can be closed
  88.146 +     * @exception IOException if something goes wrong.
  88.147 +     * @since 0.8
  88.148 +     */
  88.149 +    public static Closeable showDir(String brwsr, File directory, ClassLoader classes, String startpage) throws IOException {
  88.150 +        Launcher l = createBrowser(brwsr);
  88.151 +        if (classes != null) {
  88.152 +            l.addClassLoader(classes);
  88.153 +        }
  88.154 +        l.showDirectory(directory, startpage, classes != null);
  88.155 +        return (Closeable) l;
  88.156 +    }
  88.157 +    
  88.158 +    /** Starts an HTTP server which provides access to certain directory.
  88.159 +     * The <code>startpage</code> should be relative location inside the root 
  88.160 +     * directory. Opens a browser with URL showing the start page.
  88.161 +     * 
  88.162 +     * @param directory the root directory on disk
  88.163 +     * @param startpage relative path from the root to the page
  88.164 +     * @return instance of server that can be closed
  88.165 +     * @exception IOException if something goes wrong.
  88.166 +     */
  88.167 +    public static Closeable showDir(File directory, String startpage) throws IOException {
  88.168 +        return showDir(null, directory, null, startpage);
  88.169 +    }
  88.170 +
  88.171 +    abstract InvocationContext runMethod(InvocationContext c) throws IOException; 
  88.172 +
  88.173 +
  88.174 +    private static Class<?> loadClass(String cn) throws ClassNotFoundException {
  88.175 +        return Launcher.class.getClassLoader().loadClass(cn);
  88.176 +    }
  88.177 +
  88.178 +    void showDirectory(File directory, String startpage, boolean addClasses) throws IOException {
  88.179 +        throw new UnsupportedOperationException();
  88.180 +    }
  88.181 +
  88.182 +    void showURL(String startpage) throws IOException {
  88.183 +        throw new UnsupportedOperationException();
  88.184 +    }
  88.185 +
  88.186 +    void addClassLoader(ClassLoader classes) {
  88.187 +        throw new UnsupportedOperationException();
  88.188 +    }
  88.189 +}
    89.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    89.2 +++ b/launcher/fx/pom.xml	Mon Oct 07 14:20:58 2013 +0200
    89.3 @@ -0,0 +1,99 @@
    89.4 +<?xml version="1.0"?>
    89.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    89.6 +  <modelVersion>4.0.0</modelVersion>
    89.7 +  <parent>
    89.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
    89.9 +    <artifactId>launcher-pom</artifactId>
   89.10 +    <version>0.9-SNAPSHOT</version>
   89.11 +  </parent>
   89.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
   89.13 +  <artifactId>launcher.fx</artifactId>
   89.14 +  <version>0.9-SNAPSHOT</version>
   89.15 +  <name>FXBrwsr Launcher</name>
   89.16 +  <url>http://maven.apache.org</url>
   89.17 +    <build>
   89.18 +        <plugins>
   89.19 +            <plugin>
   89.20 +                <groupId>org.apache.maven.plugins</groupId>
   89.21 +                <artifactId>maven-compiler-plugin</artifactId>
   89.22 +                <version>2.3.2</version>
   89.23 +                <configuration>
   89.24 +                    <source>1.6</source>
   89.25 +                    <target>1.6</target>
   89.26 +                </configuration>
   89.27 +            </plugin>
   89.28 +            <plugin>
   89.29 +                <groupId>org.apache.maven.plugins</groupId>
   89.30 +                <artifactId>maven-javadoc-plugin</artifactId>
   89.31 +                <configuration>
   89.32 +                    <subpackages>org.apidesign.bck2brwsr.launcher.fx</subpackages>
   89.33 +                    <skip>false</skip>
   89.34 +                </configuration>
   89.35 +            </plugin>
   89.36 +        </plugins>
   89.37 +    </build>
   89.38 +    <properties>
   89.39 +        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   89.40 +    </properties>
   89.41 +  <dependencies>
   89.42 +    <dependency>
   89.43 +      <groupId>${project.groupId}</groupId>
   89.44 +      <artifactId>launcher</artifactId>
   89.45 +      <version>${project.version}</version>
   89.46 +    </dependency>
   89.47 +    <dependency>
   89.48 +      <groupId>org.glassfish.grizzly</groupId>
   89.49 +      <artifactId>grizzly-http-server</artifactId>
   89.50 +      <version>${grizzly.version}</version>
   89.51 +    </dependency>
   89.52 +    <dependency>
   89.53 +      <groupId>com.oracle</groupId>
   89.54 +      <artifactId>javafx</artifactId>
   89.55 +      <version>2.2</version>
   89.56 +      <scope>system</scope>
   89.57 +      <systemPath>${jfxrt.jar}</systemPath>
   89.58 +    </dependency>
   89.59 +    <dependency>
   89.60 +      <groupId>org.testng</groupId>
   89.61 +      <artifactId>testng</artifactId>
   89.62 +      <scope>test</scope>
   89.63 +    </dependency>
   89.64 +    <dependency>
   89.65 +      <groupId>org.netbeans.modules</groupId>
   89.66 +      <artifactId>org-netbeans-bootstrap</artifactId>
   89.67 +      <version>RELEASE73</version>
   89.68 +    </dependency>
   89.69 +    <dependency>
   89.70 +      <groupId>${project.groupId}</groupId>
   89.71 +      <artifactId>core</artifactId>
   89.72 +      <version>${project.version}</version>
   89.73 +      <scope>compile</scope>
   89.74 +    </dependency>
   89.75 +    <dependency>
   89.76 +      <groupId>org.ow2.asm</groupId>
   89.77 +      <artifactId>asm</artifactId>
   89.78 +      <version>4.1</version>
   89.79 +    </dependency>
   89.80 +    <dependency>
   89.81 +      <groupId>org.apidesign.html</groupId>
   89.82 +      <artifactId>net.java.html.boot</artifactId>
   89.83 +      <version>${net.java.html.version}</version>
   89.84 +    </dependency>
   89.85 +    <dependency>
   89.86 +        <groupId>org.glassfish.grizzly</groupId>
   89.87 +        <artifactId>grizzly-websockets-server</artifactId>
   89.88 +        <version>${grizzly.version}</version>
   89.89 +        <type>jar</type>
   89.90 +    </dependency>
   89.91 +    <dependency>
   89.92 +        <groupId>org.glassfish.grizzly</groupId>
   89.93 +        <artifactId>grizzly-http-servlet</artifactId>
   89.94 +        <version>${grizzly.version}</version>
   89.95 +    </dependency>    
   89.96 +    <dependency>
   89.97 +        <groupId>javax.servlet</groupId>
   89.98 +        <artifactId>javax.servlet-api</artifactId>
   89.99 +        <version>3.1.0</version>
  89.100 +    </dependency>
  89.101 +  </dependencies>
  89.102 +</project>
    90.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    90.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/BaseHTTPLauncher.java	Mon Oct 07 14:20:58 2013 +0200
    90.3 @@ -0,0 +1,751 @@
    90.4 +/**
    90.5 + * Back 2 Browser Bytecode Translator
    90.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    90.7 + *
    90.8 + * This program is free software: you can redistribute it and/or modify
    90.9 + * it under the terms of the GNU General Public License as published by
   90.10 + * the Free Software Foundation, version 2 of the License.
   90.11 + *
   90.12 + * This program is distributed in the hope that it will be useful,
   90.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   90.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   90.15 + * GNU General Public License for more details.
   90.16 + *
   90.17 + * You should have received a copy of the GNU General Public License
   90.18 + * along with this program. Look for COPYING file in the top folder.
   90.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   90.20 + */
   90.21 +package org.apidesign.bck2brwsr.launcher;
   90.22 +
   90.23 +import java.io.ByteArrayInputStream;
   90.24 +import java.io.ByteArrayOutputStream;
   90.25 +import java.io.Closeable;
   90.26 +import java.io.File;
   90.27 +import java.io.IOException;
   90.28 +import java.io.InputStream;
   90.29 +import java.io.InterruptedIOException;
   90.30 +import java.io.OutputStream;
   90.31 +import java.io.Reader;
   90.32 +import java.io.UnsupportedEncodingException;
   90.33 +import java.io.Writer;
   90.34 +import java.net.URI;
   90.35 +import java.net.URISyntaxException;
   90.36 +import java.net.URL;
   90.37 +import java.util.ArrayList;
   90.38 +import java.util.Arrays;
   90.39 +import java.util.Enumeration;
   90.40 +import java.util.LinkedHashSet;
   90.41 +import java.util.List;
   90.42 +import java.util.Set;
   90.43 +import java.util.concurrent.BlockingQueue;
   90.44 +import java.util.concurrent.Callable;
   90.45 +import java.util.concurrent.CountDownLatch;
   90.46 +import java.util.concurrent.LinkedBlockingQueue;
   90.47 +import java.util.concurrent.TimeUnit;
   90.48 +import java.util.logging.Level;
   90.49 +import java.util.logging.Logger;
   90.50 +import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
   90.51 +import org.glassfish.grizzly.PortRange;
   90.52 +import org.glassfish.grizzly.http.server.HttpHandler;
   90.53 +import org.glassfish.grizzly.http.server.HttpServer;
   90.54 +import org.glassfish.grizzly.http.server.NetworkListener;
   90.55 +import org.glassfish.grizzly.http.server.Request;
   90.56 +import org.glassfish.grizzly.http.server.Response;
   90.57 +import org.glassfish.grizzly.http.server.ServerConfiguration;
   90.58 +import org.glassfish.grizzly.http.server.StaticHttpHandler;
   90.59 +import org.glassfish.grizzly.http.util.HttpStatus;
   90.60 +import org.glassfish.grizzly.threadpool.ThreadPoolConfig;
   90.61 +import org.glassfish.grizzly.websockets.WebSocket;
   90.62 +import org.glassfish.grizzly.websockets.WebSocketAddOn;
   90.63 +import org.glassfish.grizzly.websockets.WebSocketApplication;
   90.64 +import org.glassfish.grizzly.websockets.WebSocketEngine;
   90.65 +import org.openide.util.Exceptions;
   90.66 +
   90.67 +/**
   90.68 + * Lightweight server to launch Bck2Brwsr applications and tests.
   90.69 + * Supports execution in native browser as well as Java's internal 
   90.70 + * execution engine.
   90.71 + */
   90.72 +abstract class BaseHTTPLauncher extends Launcher implements Closeable, Callable<HttpServer> {
   90.73 +    static final Logger LOG = Logger.getLogger(BaseHTTPLauncher.class.getName());
   90.74 +    private static final InvocationContext END = new InvocationContext(null, null, null);
   90.75 +    private final Set<ClassLoader> loaders = new LinkedHashSet<ClassLoader>();
   90.76 +    private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<InvocationContext>();
   90.77 +    private long timeOut;
   90.78 +    private final Res resources = new Res();
   90.79 +    private final String cmd;
   90.80 +    private Object[] brwsr;
   90.81 +    private HttpServer server;
   90.82 +    private CountDownLatch wait;
   90.83 +    
   90.84 +    public BaseHTTPLauncher(String cmd) {
   90.85 +        this.cmd = cmd;
   90.86 +        addClassLoader(BaseHTTPLauncher.class.getClassLoader());
   90.87 +        setTimeout(180000);
   90.88 +    }
   90.89 +    
   90.90 +    @Override
   90.91 +    InvocationContext runMethod(InvocationContext c) throws IOException {
   90.92 +        loaders.add(c.clazz.getClassLoader());
   90.93 +        methods.add(c);
   90.94 +        try {
   90.95 +            c.await(timeOut);
   90.96 +        } catch (InterruptedException ex) {
   90.97 +            throw new IOException(ex);
   90.98 +        }
   90.99 +        return c;
  90.100 +    }
  90.101 +    
  90.102 +    public void setTimeout(long ms) {
  90.103 +        timeOut = ms;
  90.104 +    }
  90.105 +    
  90.106 +    public void addClassLoader(ClassLoader url) {
  90.107 +        this.loaders.add(url);
  90.108 +    }
  90.109 +    
  90.110 +    ClassLoader[] loaders() {
  90.111 +        return loaders.toArray(new ClassLoader[loaders.size()]);
  90.112 +    }
  90.113 +
  90.114 +    public void showURL(String startpage) throws IOException {
  90.115 +        if (!startpage.startsWith("/")) {
  90.116 +            startpage = "/" + startpage;
  90.117 +        }
  90.118 +        HttpServer s = initServer(".", true, "");
  90.119 +        int last = startpage.lastIndexOf('/');
  90.120 +        String prefix = startpage.substring(0, last);
  90.121 +        String simpleName = startpage.substring(last);
  90.122 +        s.getServerConfiguration().addHttpHandler(new SubTree(resources, prefix), "/");
  90.123 +        server = s;
  90.124 +        try {
  90.125 +            launchServerAndBrwsr(s, simpleName);
  90.126 +        } catch (Exception ex) {
  90.127 +            throw new IOException(ex);
  90.128 +        }
  90.129 +    }
  90.130 +
  90.131 +    void showDirectory(File dir, String startpage, boolean addClasses) throws IOException {
  90.132 +        if (!startpage.startsWith("/")) {
  90.133 +            startpage = "/" + startpage;
  90.134 +        }
  90.135 +        String prefix = "";
  90.136 +        int last = startpage.lastIndexOf('/');
  90.137 +        if (last >= 0) {
  90.138 +            prefix = startpage.substring(0, last);
  90.139 +        }
  90.140 +        HttpServer s = initServer(dir.getPath(), addClasses, prefix);
  90.141 +        try {
  90.142 +            launchServerAndBrwsr(s, startpage);
  90.143 +        } catch (Exception ex) {
  90.144 +            throw new IOException(ex);
  90.145 +        }
  90.146 +    }
  90.147 +
  90.148 +    @Override
  90.149 +    public void initialize() throws IOException {
  90.150 +        try {
  90.151 +            executeInBrowser();
  90.152 +        } catch (InterruptedException ex) {
  90.153 +            final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
  90.154 +            iio.initCause(ex);
  90.155 +            throw iio;
  90.156 +        } catch (Exception ex) {
  90.157 +            if (ex instanceof IOException) {
  90.158 +                throw (IOException)ex;
  90.159 +            }
  90.160 +            if (ex instanceof RuntimeException) {
  90.161 +                throw (RuntimeException)ex;
  90.162 +            }
  90.163 +            throw new IOException(ex);
  90.164 +        }
  90.165 +    }
  90.166 +    
  90.167 +    private HttpServer initServer(String path, boolean addClasses, String vmPrefix) throws IOException {
  90.168 +        HttpServer s = HttpServer.createSimpleServer(null, new PortRange(8080, 65535));
  90.169 +        /*
  90.170 +        ThreadPoolConfig fewThreads = ThreadPoolConfig.defaultConfig().copy().
  90.171 +            setPoolName("Fx/Bck2 Brwsr").
  90.172 +            setCorePoolSize(3).
  90.173 +            setMaxPoolSize(5);
  90.174 +        ThreadPoolConfig oneKernel = ThreadPoolConfig.defaultConfig().copy().
  90.175 +            setPoolName("Kernel Fx/Bck2").
  90.176 +            setCorePoolSize(3).
  90.177 +            setMaxPoolSize(3);
  90.178 +        for (NetworkListener nl : s.getListeners()) {
  90.179 +            nl.getTransport().setWorkerThreadPoolConfig(fewThreads);
  90.180 +            nl.getTransport().setKernelThreadPoolConfig(oneKernel);
  90.181 +        }
  90.182 +        */
  90.183 +        final ServerConfiguration conf = s.getServerConfiguration();
  90.184 +        VMAndPages vm = new VMAndPages();
  90.185 +        conf.addHttpHandler(vm, "/");
  90.186 +        if (vmPrefix != null) {
  90.187 +            vm.registerVM(vmPrefix + "/bck2brwsr.js");
  90.188 +        }
  90.189 +        if (path != null) {
  90.190 +            vm.addDocRoot(path);
  90.191 +        }
  90.192 +        if (addClasses) {
  90.193 +            conf.addHttpHandler(new Classes(resources), "/classes/");
  90.194 +        }
  90.195 +        final WebSocketAddOn addon = new WebSocketAddOn();
  90.196 +        for (NetworkListener listener : s.getListeners()) {
  90.197 +            listener.registerAddOn(addon);
  90.198 +        }
  90.199 +        return s;
  90.200 +    }
  90.201 +    
  90.202 +    private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
  90.203 +        wait = new CountDownLatch(1);
  90.204 +        server = initServer(".", true, "");
  90.205 +        final ServerConfiguration conf = server.getServerConfiguration();
  90.206 +        
  90.207 +        class DynamicResourceHandler extends HttpHandler {
  90.208 +            private final InvocationContext ic;
  90.209 +            private int resourcesCount;
  90.210 +            DynamicResourceHandler delegate;
  90.211 +            public DynamicResourceHandler(InvocationContext ic) {
  90.212 +                this.ic = ic;
  90.213 +                for (Resource r : ic.resources) {
  90.214 +                    conf.addHttpHandler(this, r.httpPath);
  90.215 +                }
  90.216 +            }
  90.217 +
  90.218 +            public void close(DynamicResourceHandler del) {
  90.219 +                conf.removeHttpHandler(this);
  90.220 +                delegate = del;
  90.221 +            }
  90.222 +            
  90.223 +            @Override
  90.224 +            public void service(Request request, Response response) throws Exception {
  90.225 +                if (delegate != null) {
  90.226 +                    delegate.service(request, response);
  90.227 +                    return;
  90.228 +                }
  90.229 +                
  90.230 +                if ("/dynamic".equals(request.getRequestURI())) {
  90.231 +                    boolean webSocket = false;
  90.232 +                    String mimeType = request.getParameter("mimeType");
  90.233 +                    List<String> params = new ArrayList<String>();
  90.234 +                    for (int i = 0; ; i++) {
  90.235 +                        String p = request.getParameter("param" + i);
  90.236 +                        if (p == null) {
  90.237 +                            break;
  90.238 +                        }
  90.239 +                        params.add(p);
  90.240 +                        if ("protocol:ws".equals(p)) {
  90.241 +                            webSocket = true;
  90.242 +                            continue;
  90.243 +                        }                    }
  90.244 +                    final String cnt = request.getParameter("content");
  90.245 +                    String mangle = cnt.replace("%20", " ").replace("%0A", "\n");
  90.246 +                    ByteArrayInputStream is = new ByteArrayInputStream(mangle.getBytes("UTF-8"));
  90.247 +                    URI url;
  90.248 +                    final Resource res = new Resource(is, mimeType, "/dynamic/res" + ++resourcesCount, params.toArray(new String[params.size()]));
  90.249 +                    if (webSocket) {
  90.250 +                        url = registerWebSocket(res);
  90.251 +                    } else {
  90.252 +                        url = registerResource(res);
  90.253 +                    }
  90.254 +                    response.getWriter().write(url.toString());
  90.255 +                    response.getWriter().write("\n");
  90.256 +                    return;
  90.257 +                }
  90.258 +                
  90.259 +                for (Resource r : ic.resources) {
  90.260 +                    if (r.httpPath.equals(request.getRequestURI())) {
  90.261 +                        LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
  90.262 +                        response.setContentType(r.httpType);
  90.263 +                        r.httpContent.reset();
  90.264 +                        String[] params = null;
  90.265 +                        if (r.parameters.length != 0) {
  90.266 +                            params = new String[r.parameters.length];
  90.267 +                            for (int i = 0; i < r.parameters.length; i++) {
  90.268 +                                params[i] = request.getParameter(r.parameters[i]);
  90.269 +                                if (params[i] == null) {
  90.270 +                                    if ("http.method".equals(r.parameters[i])) {
  90.271 +                                        params[i] = request.getMethod().toString();
  90.272 +                                    } else if ("http.requestBody".equals(r.parameters[i])) {
  90.273 +                                        Reader rdr = request.getReader();
  90.274 +                                        StringBuilder sb = new StringBuilder();
  90.275 +                                        for (;;) {
  90.276 +                                            int ch = rdr.read();
  90.277 +                                            if (ch == -1) {
  90.278 +                                                break;
  90.279 +                                            }
  90.280 +                                            sb.append((char)ch);
  90.281 +                                        }
  90.282 +                                        params[i] = sb.toString();
  90.283 +                                    }
  90.284 +                                }
  90.285 +                                if (params[i] == null) {
  90.286 +                                    params[i] = "null";
  90.287 +                                }
  90.288 +                            }
  90.289 +                        }
  90.290 +                        
  90.291 +                        copyStream(r.httpContent, response.getOutputStream(), null, params);
  90.292 +                    }
  90.293 +                }
  90.294 +            }
  90.295 +            
  90.296 +            private URI registerWebSocket(Resource r) {
  90.297 +                WebSocketEngine.getEngine().register("", r.httpPath, new WS(r));
  90.298 +                return pageURL("ws", server, r.httpPath);
  90.299 +            }
  90.300 +
  90.301 +            private URI registerResource(Resource r) {
  90.302 +                if (!ic.resources.contains(r)) {
  90.303 +                    ic.resources.add(r);
  90.304 +                    conf.addHttpHandler(this, r.httpPath);
  90.305 +                }
  90.306 +                return pageURL("http", server, r.httpPath);
  90.307 +            }
  90.308 +        }
  90.309 +        
  90.310 +        conf.addHttpHandler(new Page(resources, harnessResource()), "/execute");
  90.311 +        
  90.312 +        conf.addHttpHandler(new HttpHandler() {
  90.313 +            int cnt;
  90.314 +            List<InvocationContext> cases = new ArrayList<InvocationContext>();
  90.315 +            DynamicResourceHandler prev;
  90.316 +            @Override
  90.317 +            public void service(Request request, Response response) throws Exception {
  90.318 +                String id = request.getParameter("request");
  90.319 +                String value = request.getParameter("result");
  90.320 +                if (value != null && value.indexOf((char)0xC5) != -1) {
  90.321 +                    value = toUTF8(value);
  90.322 +                }
  90.323 +                
  90.324 +                
  90.325 +                InvocationContext mi = null;
  90.326 +                int caseNmbr = -1;
  90.327 +                
  90.328 +                if (id != null && value != null) {
  90.329 +                    LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
  90.330 +                    value = decodeURL(value);
  90.331 +                    int indx = Integer.parseInt(id);
  90.332 +                    cases.get(indx).result(value, null);
  90.333 +                    if (++indx < cases.size()) {
  90.334 +                        mi = cases.get(indx);
  90.335 +                        LOG.log(Level.INFO, "Re-executing case {0}", indx);
  90.336 +                        caseNmbr = indx;
  90.337 +                    }
  90.338 +                } else {
  90.339 +                    if (!cases.isEmpty()) {
  90.340 +                        LOG.info("Re-executing test cases");
  90.341 +                        mi = cases.get(0);
  90.342 +                        caseNmbr = 0;
  90.343 +                    }
  90.344 +                }
  90.345 +                
  90.346 +                if (mi == null) {
  90.347 +                    mi = methods.take();
  90.348 +                    caseNmbr = cnt++;
  90.349 +                }
  90.350 +                if (mi == END) {
  90.351 +                    response.getWriter().write("");
  90.352 +                    wait.countDown();
  90.353 +                    cnt = 0;
  90.354 +                    LOG.log(Level.INFO, "End of data reached. Exiting.");
  90.355 +                    return;
  90.356 +                }
  90.357 +                final DynamicResourceHandler newRH = new DynamicResourceHandler(mi);
  90.358 +                if (prev != null) {
  90.359 +                    prev.close(newRH);
  90.360 +                }
  90.361 +                prev = newRH;
  90.362 +                conf.addHttpHandler(prev, "/dynamic");
  90.363 +                
  90.364 +                cases.add(mi);
  90.365 +                final String cn = mi.clazz.getName();
  90.366 +                final String mn = mi.methodName;
  90.367 +                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
  90.368 +                response.getWriter().write("{"
  90.369 +                    + "className: '" + cn + "', "
  90.370 +                    + "methodName: '" + mn + "', "
  90.371 +                    + "request: " + caseNmbr
  90.372 +                );
  90.373 +                if (mi.html != null) {
  90.374 +                    response.getWriter().write(", html: '");
  90.375 +                    response.getWriter().write(encodeJSON(mi.html));
  90.376 +                    response.getWriter().write("'");
  90.377 +                }
  90.378 +                response.getWriter().write("}");
  90.379 +            }
  90.380 +        }, "/data");
  90.381 +
  90.382 +        this.brwsr = launchServerAndBrwsr(server, "/execute");
  90.383 +    }
  90.384 +    
  90.385 +    private static String encodeJSON(String in) {
  90.386 +        StringBuilder sb = new StringBuilder();
  90.387 +        for (int i = 0; i < in.length(); i++) {
  90.388 +            char ch = in.charAt(i);
  90.389 +            if (ch < 32 || ch == '\'' || ch == '"') {
  90.390 +                sb.append("\\u");
  90.391 +                String hs = "0000" + Integer.toHexString(ch);
  90.392 +                hs = hs.substring(hs.length() - 4);
  90.393 +                sb.append(hs);
  90.394 +            } else {
  90.395 +                sb.append(ch);
  90.396 +            }
  90.397 +        }
  90.398 +        return sb.toString();
  90.399 +    }
  90.400 +    
  90.401 +    @Override
  90.402 +    public void shutdown() throws IOException {
  90.403 +        methods.offer(END);
  90.404 +        for (;;) {
  90.405 +            int prev = methods.size();
  90.406 +            try {
  90.407 +                if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
  90.408 +                    break;
  90.409 +                }
  90.410 +            } catch (InterruptedException ex) {
  90.411 +                throw new IOException(ex);
  90.412 +            }
  90.413 +            if (prev == methods.size()) {
  90.414 +                LOG.log(
  90.415 +                    Level.WARNING, 
  90.416 +                    "Timeout and no test has been executed meanwhile (at {0}). Giving up.", 
  90.417 +                    methods.size()
  90.418 +                );
  90.419 +                break;
  90.420 +            }
  90.421 +            LOG.log(Level.INFO, 
  90.422 +                "Timeout, but tests got from {0} to {1}. Trying again.", 
  90.423 +                new Object[]{prev, methods.size()}
  90.424 +            );
  90.425 +        }
  90.426 +        stopServerAndBrwsr(server, brwsr);
  90.427 +    }
  90.428 +    
  90.429 +    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
  90.430 +        for (;;) {
  90.431 +            int ch = is.read();
  90.432 +            if (ch == -1) {
  90.433 +                break;
  90.434 +            }
  90.435 +            if (ch == '$' && params.length > 0) {
  90.436 +                int cnt = is.read() - '0';
  90.437 +                if (baseURL != null && cnt == 'U' - '0') {
  90.438 +                    os.write(baseURL.getBytes("UTF-8"));
  90.439 +                } else {
  90.440 +                    if (cnt >= 0 && cnt < params.length) {
  90.441 +                        os.write(params[cnt].getBytes("UTF-8"));
  90.442 +                    } else {
  90.443 +                        os.write('$');
  90.444 +                        os.write(cnt + '0');
  90.445 +                    }
  90.446 +                }
  90.447 +            } else {
  90.448 +                os.write(ch);
  90.449 +            }
  90.450 +        }
  90.451 +    }
  90.452 +
  90.453 +    private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
  90.454 +        server.start();
  90.455 +        URI uri = pageURL("http", server, page);
  90.456 +        return showBrwsr(uri);
  90.457 +    }
  90.458 +    private static String toUTF8(String value) throws UnsupportedEncodingException {
  90.459 +        byte[] arr = new byte[value.length()];
  90.460 +        for (int i = 0; i < arr.length; i++) {
  90.461 +            arr[i] = (byte)value.charAt(i);
  90.462 +        }
  90.463 +        return new String(arr, "UTF-8");
  90.464 +    }
  90.465 +    
  90.466 +    private static String decodeURL(String s) {
  90.467 +        for (;;) {
  90.468 +            int pos = s.indexOf('%');
  90.469 +            if (pos == -1) {
  90.470 +                return s;
  90.471 +            }
  90.472 +            int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
  90.473 +            s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
  90.474 +        }
  90.475 +    }
  90.476 +    
  90.477 +    private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
  90.478 +        if (brwsr == null) {
  90.479 +            return;
  90.480 +        }
  90.481 +        Process process = (Process)brwsr[0];
  90.482 +        
  90.483 +        server.stop();
  90.484 +        InputStream stdout = process.getInputStream();
  90.485 +        InputStream stderr = process.getErrorStream();
  90.486 +        drain("StdOut", stdout);
  90.487 +        drain("StdErr", stderr);
  90.488 +        process.destroy();
  90.489 +        int res;
  90.490 +        try {
  90.491 +            res = process.waitFor();
  90.492 +        } catch (InterruptedException ex) {
  90.493 +            throw new IOException(ex);
  90.494 +        }
  90.495 +        LOG.log(Level.INFO, "Exit code: {0}", res);
  90.496 +
  90.497 +        deleteTree((File)brwsr[1]);
  90.498 +    }
  90.499 +    
  90.500 +    private static void drain(String name, InputStream is) throws IOException {
  90.501 +        int av = is.available();
  90.502 +        if (av > 0) {
  90.503 +            StringBuilder sb = new StringBuilder();
  90.504 +            sb.append("v== ").append(name).append(" ==v\n");
  90.505 +            while (av-- > 0) {
  90.506 +                sb.append((char)is.read());
  90.507 +            }
  90.508 +            sb.append("\n^== ").append(name).append(" ==^");
  90.509 +            LOG.log(Level.INFO, sb.toString());
  90.510 +        }
  90.511 +    }
  90.512 +
  90.513 +    private void deleteTree(File file) {
  90.514 +        if (file == null) {
  90.515 +            return;
  90.516 +        }
  90.517 +        File[] arr = file.listFiles();
  90.518 +        if (arr != null) {
  90.519 +            for (File s : arr) {
  90.520 +                deleteTree(s);
  90.521 +            }
  90.522 +        }
  90.523 +        file.delete();
  90.524 +    }
  90.525 +
  90.526 +    @Override
  90.527 +    public HttpServer call() throws Exception {
  90.528 +        return server;
  90.529 +    }
  90.530 +    
  90.531 +    @Override
  90.532 +    public void close() throws IOException {
  90.533 +        shutdown();
  90.534 +    }
  90.535 +
  90.536 +    protected Object[] showBrwsr(URI uri) throws IOException {
  90.537 +        LOG.log(Level.INFO, "Showing {0}", uri);
  90.538 +        if (cmd == null) {
  90.539 +            try {
  90.540 +                LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
  90.541 +                    System.getProperty("java.vm.name"),
  90.542 +                    System.getProperty("java.vm.vendor"),
  90.543 +                    System.getProperty("java.vm.version"),
  90.544 +                });
  90.545 +                java.awt.Desktop.getDesktop().browse(uri);
  90.546 +                LOG.log(Level.INFO, "Desktop.browse successfully finished");
  90.547 +                return null;
  90.548 +            } catch (UnsupportedOperationException ex) {
  90.549 +                LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
  90.550 +                LOG.log(Level.FINE, null, ex);
  90.551 +            }
  90.552 +        }
  90.553 +        {
  90.554 +            String cmdName = cmd == null ? "xdg-open" : cmd;
  90.555 +            String[] cmdArr = { 
  90.556 +                cmdName, uri.toString()
  90.557 +            };
  90.558 +            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
  90.559 +            final Process process = Runtime.getRuntime().exec(cmdArr);
  90.560 +            return new Object[] { process, null };
  90.561 +        }
  90.562 +    }
  90.563 +
  90.564 +    abstract void generateBck2BrwsrJS(StringBuilder sb, Res loader) throws IOException;
  90.565 +    abstract String harnessResource();
  90.566 +
  90.567 +    private static URI pageURL(String protocol, HttpServer server, final String page) {
  90.568 +        NetworkListener listener = server.getListeners().iterator().next();
  90.569 +        int port = listener.getPort();
  90.570 +        try {
  90.571 +            return new URI(protocol + "://localhost:" + port + page);
  90.572 +        } catch (URISyntaxException ex) {
  90.573 +            throw new IllegalStateException(ex);
  90.574 +        }
  90.575 +    }
  90.576 +
  90.577 +    class Res {
  90.578 +        public InputStream get(String resource) throws IOException {
  90.579 +            URL u = null;
  90.580 +            for (ClassLoader l : loaders) {
  90.581 +                Enumeration<URL> en = l.getResources(resource);
  90.582 +                while (en.hasMoreElements()) {
  90.583 +                    u = en.nextElement();
  90.584 +                    if (u.toExternalForm().matches("^.*emul.*rt\\.jar.*$")) {
  90.585 +                        return u.openStream();
  90.586 +                    }
  90.587 +                }
  90.588 +            }
  90.589 +            if (u != null) {
  90.590 +                if (u.toExternalForm().contains("rt.jar")) {
  90.591 +                    LOG.log(Level.WARNING, "Fallback to bootclasspath for {0}", u);
  90.592 +                }
  90.593 +                return u.openStream();
  90.594 +            }
  90.595 +            throw new IOException("Can't find " + resource);
  90.596 +        }
  90.597 +    }
  90.598 +
  90.599 +    private static class Page extends HttpHandler {
  90.600 +        final String resource;
  90.601 +        private final String[] args;
  90.602 +        private final Res res;
  90.603 +        
  90.604 +        public Page(Res res, String resource, String... args) {
  90.605 +            this.res = res;
  90.606 +            this.resource = resource;
  90.607 +            this.args = args.length == 0 ? new String[] { "$0" } : args;
  90.608 +        }
  90.609 +
  90.610 +        @Override
  90.611 +        public void service(Request request, Response response) throws Exception {
  90.612 +            String r = computePage(request);
  90.613 +            if (r.startsWith("/")) {
  90.614 +                r = r.substring(1);
  90.615 +            }
  90.616 +            String[] replace = {};
  90.617 +            if (r.endsWith(".html")) {
  90.618 +                response.setContentType("text/html");
  90.619 +                LOG.info("Content type text/html");
  90.620 +                replace = args;
  90.621 +            }
  90.622 +            if (r.endsWith(".xhtml")) {
  90.623 +                response.setContentType("application/xhtml+xml");
  90.624 +                LOG.info("Content type application/xhtml+xml");
  90.625 +                replace = args;
  90.626 +            }
  90.627 +            OutputStream os = response.getOutputStream();
  90.628 +            try { 
  90.629 +                InputStream is = res.get(r);
  90.630 +                copyStream(is, os, request.getRequestURL().toString(), replace);
  90.631 +            } catch (IOException ex) {
  90.632 +                response.setDetailMessage(ex.getLocalizedMessage());
  90.633 +                response.setError();
  90.634 +                response.setStatus(404);
  90.635 +            }
  90.636 +        }
  90.637 +
  90.638 +        protected String computePage(Request request) {
  90.639 +            String r = resource;
  90.640 +            if (r == null) {
  90.641 +                r = request.getHttpHandlerPath();
  90.642 +            }
  90.643 +            return r;
  90.644 +        }
  90.645 +    }
  90.646 +    
  90.647 +    private static class SubTree extends Page {
  90.648 +
  90.649 +        public SubTree(Res res, String resource, String... args) {
  90.650 +            super(res, resource, args);
  90.651 +        }
  90.652 +
  90.653 +        @Override
  90.654 +        protected String computePage(Request request) {
  90.655 +            return resource + request.getHttpHandlerPath();
  90.656 +        }
  90.657 +        
  90.658 +        
  90.659 +    }
  90.660 +
  90.661 +    private class VMAndPages extends StaticHttpHandler {
  90.662 +        private String vmResource;
  90.663 +        
  90.664 +        public VMAndPages() {
  90.665 +            super((String[]) null);
  90.666 +        }
  90.667 +        
  90.668 +        @Override
  90.669 +        public void service(Request request, Response response) throws Exception {
  90.670 +            if (request.getRequestURI().equals(vmResource)) {
  90.671 +                response.setCharacterEncoding("UTF-8");
  90.672 +                response.setContentType("text/javascript");
  90.673 +                StringBuilder sb = new StringBuilder();
  90.674 +                generateBck2BrwsrJS(sb, BaseHTTPLauncher.this.resources);
  90.675 +                response.getWriter().write(sb.toString());
  90.676 +            } else {
  90.677 +                super.service(request, response);
  90.678 +            }
  90.679 +        }
  90.680 +
  90.681 +        private void registerVM(String vmResource) {
  90.682 +            this.vmResource = vmResource;
  90.683 +        }
  90.684 +    }
  90.685 +
  90.686 +    private static class Classes extends HttpHandler {
  90.687 +        private final Res loader;
  90.688 +
  90.689 +        public Classes(Res loader) {
  90.690 +            this.loader = loader;
  90.691 +        }
  90.692 +
  90.693 +        @Override
  90.694 +        public void service(Request request, Response response) throws Exception {
  90.695 +            String res = request.getHttpHandlerPath();
  90.696 +            if (res.startsWith("/")) {
  90.697 +                res = res.substring(1);
  90.698 +            }
  90.699 +            InputStream is = null;
  90.700 +            try {
  90.701 +                is = loader.get(res);
  90.702 +                response.setContentType("text/javascript");
  90.703 +                Writer w = response.getWriter();
  90.704 +                w.append("[");
  90.705 +                for (int i = 0;; i++) {
  90.706 +                    int b = is.read();
  90.707 +                    if (b == -1) {
  90.708 +                        break;
  90.709 +                    }
  90.710 +                    if (i > 0) {
  90.711 +                        w.append(", ");
  90.712 +                    }
  90.713 +                    if (i % 20 == 0) {
  90.714 +                        w.write("\n");
  90.715 +                    }
  90.716 +                    if (b > 127) {
  90.717 +                        b = b - 256;
  90.718 +                    }
  90.719 +                    w.append(Integer.toString(b));
  90.720 +                }
  90.721 +                w.append("\n]");
  90.722 +            } catch (IOException ex) {
  90.723 +                response.setStatus(HttpStatus.NOT_FOUND_404);
  90.724 +                response.setError();
  90.725 +                response.setDetailMessage(ex.getMessage());
  90.726 +            } finally {
  90.727 +                if (is != null) {
  90.728 +                    is.close();
  90.729 +                }
  90.730 +            }
  90.731 +        }
  90.732 +    }
  90.733 +    private static class WS extends WebSocketApplication {
  90.734 +
  90.735 +        private final Resource r;
  90.736 +
  90.737 +        private WS(Resource r) {
  90.738 +            this.r = r;
  90.739 +        }
  90.740 +
  90.741 +        @Override
  90.742 +        public void onMessage(WebSocket socket, String text) {
  90.743 +            try {
  90.744 +                r.httpContent.reset();
  90.745 +                ByteArrayOutputStream out = new ByteArrayOutputStream();
  90.746 +                copyStream(r.httpContent, out, null, text);
  90.747 +                String s = new String(out.toByteArray(), "UTF-8");
  90.748 +                socket.send(s);
  90.749 +            } catch (IOException ex) {
  90.750 +                Exceptions.printStackTrace(ex);
  90.751 +            }
  90.752 +        }
  90.753 +
  90.754 +    }}
    91.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    91.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/FXBrwsrLauncher.java	Mon Oct 07 14:20:58 2013 +0200
    91.3 @@ -0,0 +1,186 @@
    91.4 +/**
    91.5 + * Back 2 Browser Bytecode Translator
    91.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    91.7 + *
    91.8 + * This program is free software: you can redistribute it and/or modify
    91.9 + * it under the terms of the GNU General Public License as published by
   91.10 + * the Free Software Foundation, version 2 of the License.
   91.11 + *
   91.12 + * This program is distributed in the hope that it will be useful,
   91.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   91.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   91.15 + * GNU General Public License for more details.
   91.16 + *
   91.17 + * You should have received a copy of the GNU General Public License
   91.18 + * along with this program. Look for COPYING file in the top folder.
   91.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   91.20 + */
   91.21 +package org.apidesign.bck2brwsr.launcher;
   91.22 +
   91.23 +import java.io.File;
   91.24 +import org.apidesign.bck2brwsr.launcher.fximpl.FXBrwsr;
   91.25 +import java.io.IOException;
   91.26 +import java.io.InputStream;
   91.27 +import java.lang.reflect.Method;
   91.28 +import java.net.JarURLConnection;
   91.29 +import java.net.URI;
   91.30 +import java.net.URISyntaxException;
   91.31 +import java.net.URL;
   91.32 +import java.net.URLClassLoader;
   91.33 +import java.util.ArrayList;
   91.34 +import java.util.Enumeration;
   91.35 +import java.util.List;
   91.36 +
   91.37 +import java.util.concurrent.Executors;
   91.38 +import java.util.jar.Manifest;
   91.39 +import java.util.logging.Level;
   91.40 +import java.util.logging.Logger;
   91.41 +import javafx.application.Platform;
   91.42 +import org.apidesign.bck2brwsr.launcher.fximpl.JVMBridge;
   91.43 +import org.openide.util.Exceptions;
   91.44 +
   91.45 +/**
   91.46 + *
   91.47 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   91.48 + */
   91.49 +final class FXBrwsrLauncher extends BaseHTTPLauncher {
   91.50 +    private static final Logger LOG = Logger.getLogger(FXBrwsrLauncher.class.getName());
   91.51 +    static {
   91.52 +        try {
   91.53 +            Method m = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
   91.54 +            m.setAccessible(true);
   91.55 +            URL l = new URL("file://" + System.getProperty("java.home") + "/lib/jfxrt.jar");
   91.56 +            LOG.log(Level.INFO, "url : {0}", l);
   91.57 +            m.invoke(ClassLoader.getSystemClassLoader(), l);
   91.58 +        } catch (Exception ex) {
   91.59 +            throw new LinkageError("Can't add jfxrt.jar on the classpath", ex);
   91.60 +        }
   91.61 +    }
   91.62 +
   91.63 +    public FXBrwsrLauncher(String ignore) {
   91.64 +        super(null);
   91.65 +    }
   91.66 +
   91.67 +    @Override
   91.68 +    protected Object[] showBrwsr(final URI url) throws IOException {
   91.69 +        try {
   91.70 +            LOG.log(Level.INFO, "showBrwsr for {0}", url);
   91.71 +            JVMBridge.registerClassLoaders(loaders());
   91.72 +            LOG.info("About to launch WebView");
   91.73 +            Executors.newSingleThreadExecutor().submit(new Runnable() {
   91.74 +                @Override
   91.75 +                public void run() {
   91.76 +                    LOG.log(Level.INFO, "In FX thread. Launching!");
   91.77 +                    try {
   91.78 +                        List<String> params = new ArrayList<String>();
   91.79 +                        params.add(url.toString());
   91.80 +                        if (isDebugged()) {
   91.81 +                            params.add("--toolbar=true");
   91.82 +                            params.add("--firebug=true");
   91.83 +                            String ud = System.getProperty("netbeans.user");
   91.84 +                            if (ud != null) {
   91.85 +                                params.add("--userdir=" + ud);
   91.86 +                            }
   91.87 +                        }
   91.88 +                        FXBrwsr.launch(FXBrwsr.class, params.toArray(new String[params.size()]));
   91.89 +                        LOG.log(Level.INFO, "Launcher is back. Closing");
   91.90 +                        close();
   91.91 +                        System.exit(0);
   91.92 +                    } catch (Throwable ex) {
   91.93 +                        LOG.log(Level.WARNING, "Error launching Web View", ex);
   91.94 +                    }
   91.95 +                }
   91.96 +            });
   91.97 +        } catch (Throwable ex) {
   91.98 +            LOG.log(Level.WARNING, "Can't open WebView", ex);
   91.99 +        }
  91.100 +        return null;
  91.101 +    }
  91.102 +    
  91.103 +    @Override
  91.104 +    void generateBck2BrwsrJS(StringBuilder sb, Res loader) throws IOException {
  91.105 +        sb.append("(function() {\n"
  91.106 +            + "  var impl = this.bck2brwsr;\n"
  91.107 +            + "  this.bck2brwsr = function() { return impl; };\n");
  91.108 +        sb.append("})(window);\n");
  91.109 +        JVMBridge.onBck2BrwsrLoad();
  91.110 +    }
  91.111 +
  91.112 +    @Override
  91.113 +    public void close() throws IOException {
  91.114 +        super.close();
  91.115 +        Platform.exit();
  91.116 +    }
  91.117 +
  91.118 +    String harnessResource() {
  91.119 +        return "org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml";
  91.120 +    }
  91.121 +
  91.122 +    public static void main(String... args) throws IOException {
  91.123 +        String startPage = null;
  91.124 +
  91.125 +        final ClassLoader cl = FXBrwsrLauncher.class.getClassLoader();
  91.126 +        URL[] manifestURL = { null };
  91.127 +        startPage = findStartPage(cl, startPage, manifestURL);
  91.128 +        if (startPage == null) {
  91.129 +            throw new NullPointerException("Can't find StartPage tag in manifests!");
  91.130 +        }
  91.131 +        
  91.132 +        File dir = new File(".");
  91.133 +        if (manifestURL[0].getProtocol().equals("jar")) {
  91.134 +            try {
  91.135 +                dir = new File(
  91.136 +                    ((JarURLConnection)manifestURL[0].openConnection()).getJarFileURL().toURI()
  91.137 +                ).getParentFile();
  91.138 +            } catch (URISyntaxException ex) {
  91.139 +                LOG.log(Level.WARNING, "Can't find root directory", ex);
  91.140 +            }
  91.141 +        }
  91.142 +        
  91.143 +        Launcher.showDir("fxbrwsr", dir, cl, startPage);
  91.144 +    }
  91.145 +    
  91.146 +    private static String findStartPage(
  91.147 +        final ClassLoader cl, String startPage, URL[] startURL
  91.148 +    ) throws IOException {
  91.149 +        Enumeration<URL> en = cl.getResources("META-INF/MANIFEST.MF");
  91.150 +        while (en.hasMoreElements()) {
  91.151 +            URL url = en.nextElement();
  91.152 +            Manifest mf;
  91.153 +            InputStream is = null;
  91.154 +            try {
  91.155 +                is = url.openStream();
  91.156 +                mf = new Manifest(is);
  91.157 +            } finally {
  91.158 +                if (is != null) is.close();
  91.159 +            }
  91.160 +            String sp = mf.getMainAttributes().getValue("StartPage");
  91.161 +            if (sp != null) {
  91.162 +                startPage = sp;
  91.163 +                if (startURL != null) {
  91.164 +                    startURL[0] = url;
  91.165 +                }
  91.166 +                break;
  91.167 +            }
  91.168 +        }
  91.169 +        return startPage;
  91.170 +    }
  91.171 +    
  91.172 +    private static boolean isDebugged() {
  91.173 +        try {
  91.174 +            return isDebuggedImpl();
  91.175 +        } catch (LinkageError e) {
  91.176 +            return false;
  91.177 +        }
  91.178 +    }
  91.179 +
  91.180 +    private static boolean isDebuggedImpl() {
  91.181 +        java.lang.management.RuntimeMXBean runtime;
  91.182 +        runtime = java.lang.management.ManagementFactory.getRuntimeMXBean();
  91.183 +        List<String> args = runtime.getInputArguments();
  91.184 +        if (args.contains("-Xdebug")) { // NOI18N
  91.185 +            return true;
  91.186 +        }
  91.187 +        return false;
  91.188 +    }
  91.189 +}
    92.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    92.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fx/LauncherFX.java	Mon Oct 07 14:20:58 2013 +0200
    92.3 @@ -0,0 +1,32 @@
    92.4 +/**
    92.5 + * Back 2 Browser Bytecode Translator
    92.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    92.7 + *
    92.8 + * This program is free software: you can redistribute it and/or modify
    92.9 + * it under the terms of the GNU General Public License as published by
   92.10 + * the Free Software Foundation, version 2 of the License.
   92.11 + *
   92.12 + * This program is distributed in the hope that it will be useful,
   92.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   92.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   92.15 + * GNU General Public License for more details.
   92.16 + *
   92.17 + * You should have received a copy of the GNU General Public License
   92.18 + * along with this program. Look for COPYING file in the top folder.
   92.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   92.20 + */
   92.21 +package org.apidesign.bck2brwsr.launcher.fx;
   92.22 +
   92.23 +import org.apidesign.bck2brwsr.launcher.Launcher;
   92.24 +
   92.25 +/** This is a launcher for the <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
   92.26 + * project that is using <b>JavaFX</b>'s WebView to display the browser inside
   92.27 + * real Java virtual machine. Use {@link Launcher} methods to access this
   92.28 + * functionality via public, supported methods.
   92.29 + *
   92.30 + * @author Jaroslav Tulach
   92.31 + */
   92.32 +public final class LauncherFX {
   92.33 +    private LauncherFX() {
   92.34 +    }
   92.35 +}
    93.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    93.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/BrowserToolbar.java	Mon Oct 07 14:20:58 2013 +0200
    93.3 @@ -0,0 +1,379 @@
    93.4 +/**
    93.5 + * Back 2 Browser Bytecode Translator
    93.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    93.7 + *
    93.8 + * This program is free software: you can redistribute it and/or modify
    93.9 + * it under the terms of the GNU General Public License as published by
   93.10 + * the Free Software Foundation, version 2 of the License.
   93.11 + *
   93.12 + * This program is distributed in the hope that it will be useful,
   93.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   93.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   93.15 + * GNU General Public License for more details.
   93.16 + *
   93.17 + * You should have received a copy of the GNU General Public License
   93.18 + * along with this program. Look for COPYING file in the top folder.
   93.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   93.20 + */
   93.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   93.22 +
   93.23 +import java.util.ArrayList;
   93.24 +import java.util.List;
   93.25 +import javafx.beans.InvalidationListener;
   93.26 +import javafx.beans.Observable;
   93.27 +import javafx.beans.value.ChangeListener;
   93.28 +import javafx.beans.value.ObservableValue;
   93.29 +import javafx.collections.FXCollections;
   93.30 +import javafx.scene.control.ComboBox;
   93.31 +import javafx.scene.control.ScrollPane;
   93.32 +import javafx.scene.control.Separator;
   93.33 +import javafx.scene.control.Toggle;
   93.34 +import javafx.scene.control.ToggleButton;
   93.35 +import javafx.scene.control.ToggleGroup;
   93.36 +import javafx.scene.control.ToolBar;
   93.37 +import javafx.scene.control.Tooltip;
   93.38 +import javafx.scene.image.Image;
   93.39 +import javafx.scene.image.ImageView;
   93.40 +import javafx.scene.layout.Pane;
   93.41 +import javafx.scene.web.WebEngine;
   93.42 +import javafx.scene.web.WebView;
   93.43 +
   93.44 +final class BrowserToolbar extends ToolBar {
   93.45 +    private final ArrayList<ResizeBtn> resizeButtons;
   93.46 +    private final WebView webView;
   93.47 +    private final Pane container;
   93.48 +    private final ToggleGroup resizeGroup = new ToggleGroup();
   93.49 +    private final ComboBox<String> comboZoom = new ComboBox<String>();
   93.50 +    
   93.51 +    BrowserToolbar(WebView webView, Pane container, boolean useFirebug) {
   93.52 +        this.webView = webView;
   93.53 +        this.container = container;
   93.54 +        
   93.55 +        List<ResizeOption> options = ResizeOption.loadAll();
   93.56 +        options.add( 0, ResizeOption.SIZE_TO_FIT );
   93.57 +        resizeButtons = new ArrayList<ResizeBtn>( options.size() );
   93.58 +
   93.59 +        for( ResizeOption ro : options ) {
   93.60 +            ResizeBtn button = new ResizeBtn(ro);
   93.61 +            resizeButtons.add( button );
   93.62 +            resizeGroup.getToggles().add( button );
   93.63 +            getItems().add( button );
   93.64 +        }
   93.65 +        resizeButtons.get( 0 ).setSelected( true );
   93.66 +        resizeGroup.selectedToggleProperty().addListener( new InvalidationListener() {
   93.67 +
   93.68 +            @Override
   93.69 +            public void invalidated( Observable o ) {
   93.70 +                resize();
   93.71 +            }
   93.72 +        });
   93.73 +        
   93.74 +        getItems().add( new Separator() );
   93.75 +
   93.76 +        getItems().add( comboZoom );
   93.77 +        ArrayList<String> zoomModel = new ArrayList<String>( 6 );
   93.78 +        zoomModel.add( "200%" ); //NOI18N
   93.79 +        zoomModel.add( "150%" ); //NOI18N
   93.80 +        zoomModel.add( "100%" ); //NOI18N
   93.81 +        zoomModel.add( "75%" ); //NOI18N
   93.82 +        zoomModel.add( "50%" ); //NOI18N
   93.83 +        comboZoom.setItems( FXCollections.observableList( zoomModel ) );
   93.84 +        comboZoom.setEditable( true );
   93.85 +        comboZoom.setValue( "100%" ); //NOI18N
   93.86 +        comboZoom.valueProperty().addListener( new ChangeListener<String>() {
   93.87 +
   93.88 +            @Override
   93.89 +            public void changed( ObservableValue<? extends String> ov, String t, String t1 ) {
   93.90 +                String newZoom = zoom( t1 );
   93.91 +                comboZoom.setValue( newZoom );
   93.92 +            }
   93.93 +        });
   93.94 +        
   93.95 +        if (useFirebug) {
   93.96 +            getItems().add(new Separator());
   93.97 +
   93.98 +            final ToggleButton firebug = new ToggleButton(null, new ImageView(
   93.99 +                new Image(BrowserToolbar.class.getResourceAsStream("firebug.png"))
  93.100 +            ));
  93.101 +            firebug.setTooltip(new Tooltip("Show/Hide firebug"));
  93.102 +            firebug.selectedProperty().addListener(new InvalidationListener() {
  93.103 +                @Override
  93.104 +                public void invalidated(Observable o) {
  93.105 +                    toggleFireBug(firebug.isSelected());
  93.106 +                }
  93.107 +            });
  93.108 +            getItems().add(firebug);
  93.109 +        }
  93.110 +    }
  93.111 +
  93.112 +    private String zoom( String zoomFactor ) {
  93.113 +        if( zoomFactor.trim().isEmpty() )
  93.114 +            return null;
  93.115 +
  93.116 +        try {
  93.117 +            zoomFactor = zoomFactor.replaceAll( "\\%", ""); //NOI18N
  93.118 +            zoomFactor = zoomFactor.trim();
  93.119 +            double zoom = Double.parseDouble( zoomFactor );
  93.120 +            zoom = Math.abs( zoom )/100;
  93.121 +            if( zoom <= 0.0 )
  93.122 +                return null;
  93.123 +            webView.impl_setScale( zoom );
  93.124 +            return (int)(100*zoom) + "%"; //NOI18N
  93.125 +        } catch( NumberFormatException nfe ) {
  93.126 +            //ignore
  93.127 +        }
  93.128 +        return null;
  93.129 +    }
  93.130 +
  93.131 +    private void resize() {
  93.132 +        Toggle selection = resizeGroup.getSelectedToggle();
  93.133 +        if( selection instanceof ResizeBtn ) {
  93.134 +            ResizeOption ro = ((ResizeBtn)selection).getResizeOption();
  93.135 +            if( ro == ResizeOption.SIZE_TO_FIT ) {
  93.136 +                _autofit();
  93.137 +            } else {
  93.138 +                _resize( ro.getWidth(), ro.getHeight() );
  93.139 +            }
  93.140 +        }
  93.141 +
  93.142 +    }
  93.143 +
  93.144 +    private void _resize( final double width, final double height ) {
  93.145 +        ScrollPane scroll;
  93.146 +        if( !(container.getChildren().get( 0) instanceof ScrollPane) ) {
  93.147 +            scroll = new ScrollPane();
  93.148 +            scroll.setContent( webView );
  93.149 +            container.getChildren().clear();
  93.150 +            container.getChildren().add( scroll );
  93.151 +        } else {
  93.152 +            scroll = ( ScrollPane ) container.getChildren().get( 0 );
  93.153 +        }
  93.154 +        scroll.setPrefViewportWidth( width );
  93.155 +        scroll.setPrefViewportHeight(height );
  93.156 +        webView.setMaxWidth( width );
  93.157 +        webView.setMaxHeight( height );
  93.158 +        webView.setMinWidth( width );
  93.159 +        webView.setMinHeight( height );
  93.160 +    }
  93.161 +
  93.162 +    private void _autofit() {
  93.163 +        if( container.getChildren().get( 0) instanceof ScrollPane ) {
  93.164 +            container.getChildren().clear();
  93.165 +            container.getChildren().add( webView );
  93.166 +        }
  93.167 +        webView.setMaxWidth( Integer.MAX_VALUE );
  93.168 +        webView.setMaxHeight( Integer.MAX_VALUE );
  93.169 +        webView.setMinWidth( -1 );
  93.170 +        webView.setMinHeight( -1 );
  93.171 +        webView.autosize();
  93.172 +    }
  93.173 +
  93.174 +    final void toggleFireBug(boolean enable) {
  93.175 +        WebEngine eng = webView.getEngine();
  93.176 +        Object installed = eng.executeScript("window.Firebug");
  93.177 +        if ("undefined".equals(installed)) {
  93.178 +            StringBuilder sb = new StringBuilder();
  93.179 +            sb.append("var scr = window.document.createElement('script');\n");
  93.180 +            sb.append("scr.type = 'text/javascript';\n");
  93.181 +            sb.append("scr.src = 'https://getfirebug.com/firebug-lite.js';\n");
  93.182 +            sb.append("scr.text = '{ startOpened: true }';\n");
  93.183 +            sb.append("var head = window.document.getElementsByTagName('head')[0];");
  93.184 +            sb.append("head.appendChild(scr);\n");
  93.185 +            sb.append("var html = window.document.getElementsByTagName('html')[0];");
  93.186 +            sb.append("html.debug = true;\n");
  93.187 +            eng.executeScript(sb.toString());
  93.188 +        } else {
  93.189 +            if (enable) {
  93.190 +                eng.executeScript("Firebug.chrome.open()");
  93.191 +            } else {
  93.192 +                eng.executeScript("Firebug.chrome.close()");
  93.193 +            }
  93.194 +        }
  93.195 +    }
  93.196 +
  93.197 +    /**
  93.198 +     * Button to resize the browser window.
  93.199 +     * Taken from NetBeans. Kept GPLwithCPEx license.
  93.200 +     * Portions Copyrighted 2012 Sun Microsystems, Inc.
  93.201 +     *
  93.202 +     * @author S. Aubrecht
  93.203 +     */
  93.204 +    static final class ResizeBtn extends ToggleButton {
  93.205 +
  93.206 +        private final ResizeOption resizeOption;
  93.207 +
  93.208 +        ResizeBtn(ResizeOption resizeOption) {
  93.209 +            super(null, new ImageView(toImage(resizeOption)));
  93.210 +            this.resizeOption = resizeOption;
  93.211 +            setTooltip(new Tooltip(resizeOption.getToolTip()));
  93.212 +        }
  93.213 +
  93.214 +        ResizeOption getResizeOption() {
  93.215 +            return resizeOption;
  93.216 +        }
  93.217 +
  93.218 +        static Image toImage(ResizeOption ro) {
  93.219 +            if (ro == ResizeOption.SIZE_TO_FIT) {
  93.220 +                return ResizeOption.Type.CUSTOM.getImage();
  93.221 +            }
  93.222 +            return ro.getType().getImage();
  93.223 +        }
  93.224 +    }
  93.225 +
  93.226 +    /**
  93.227 +     * Immutable value class describing a single button to resize web browser window.
  93.228 +     * Taken from NetBeans. Kept GPLwithCPEx license.
  93.229 +     * Portions Copyrighted 2012 Sun Microsystems, Inc.
  93.230 +     *
  93.231 +     * @author S. Aubrecht
  93.232 +     */
  93.233 +    static final class ResizeOption {
  93.234 +
  93.235 +        private final Type type;
  93.236 +        private final String displayName;
  93.237 +        private final int width;
  93.238 +        private final int height;
  93.239 +        private final boolean isDefault;
  93.240 +
  93.241 +        enum Type {
  93.242 +            DESKTOP("desktop.png"), 
  93.243 +            TABLET_PORTRAIT("tabletPortrait.png"), 
  93.244 +            TABLET_LANDSCAPE("tabletLandscape.png"), 
  93.245 +            SMARTPHONE_PORTRAIT("handheldPortrait.png"), 
  93.246 +            SMARTPHONE_LANDSCAPE("handheldLandscape.png"), 
  93.247 +            WIDESCREEN("widescreen.png"), 
  93.248 +            NETBOOK("netbook.png"), 
  93.249 +            CUSTOM("sizeToFit.png");
  93.250 +            
  93.251 +            
  93.252 +            private final String resource;
  93.253 +
  93.254 +            private Type(String r) {
  93.255 +                resource = r;
  93.256 +            }
  93.257 +
  93.258 +            public Image getImage() {
  93.259 +                return new Image(Type.class.getResourceAsStream(resource));
  93.260 +            }
  93.261 +        }
  93.262 +
  93.263 +        private ResizeOption(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
  93.264 +            super();
  93.265 +            this.type = type;
  93.266 +            this.displayName = displayName;
  93.267 +            this.width = width;
  93.268 +            this.height = height;
  93.269 +            this.isDefault = isDefault;
  93.270 +        }
  93.271 +
  93.272 +        static List<ResizeOption> loadAll() {
  93.273 +            List<ResizeOption> res = new ArrayList<ResizeOption>(10);
  93.274 +            res.add(ResizeOption.create(ResizeOption.Type.DESKTOP, "Desktop", 1280, 1024, true, true));
  93.275 +            res.add(ResizeOption.create(ResizeOption.Type.TABLET_LANDSCAPE, "Tablet Landscape", 1024, 768, true, true));
  93.276 +            res.add(ResizeOption.create(ResizeOption.Type.TABLET_PORTRAIT, "Tablet Portrait", 768, 1024, true, true));
  93.277 +            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_LANDSCAPE, "Smartphone Landscape", 480, 320, true, true));
  93.278 +            res.add(ResizeOption.create(ResizeOption.Type.SMARTPHONE_PORTRAIT, "Smartphone Portrait", 320, 480, true, true));
  93.279 +            res.add(ResizeOption.create(ResizeOption.Type.WIDESCREEN, "Widescreen", 1680, 1050, false, true));
  93.280 +            res.add(ResizeOption.create(ResizeOption.Type.NETBOOK, "Netbook", 1024, 600, false, true));
  93.281 +            return res;
  93.282 +        }
  93.283 +        
  93.284 +        /**
  93.285 +         * Creates a new instance.
  93.286 +         * @param type
  93.287 +         * @param displayName Display name to show in tooltip, cannot be empty.
  93.288 +         * @param width Screen width
  93.289 +         * @param height Screen height
  93.290 +         * @param showInToolbar True to show in web developer toolbar.
  93.291 +         * @param isDefault True if this is a predefined option that cannot be removed.
  93.292 +         * @return New instance.
  93.293 +         */
  93.294 +        public static ResizeOption create(Type type, String displayName, int width, int height, boolean showInToolbar, boolean isDefault) {
  93.295 +            if (width <= 0 || height <= 0) {
  93.296 +                throw new IllegalArgumentException("Invalid screen dimensions: " + width + " x " + height); //NOI18N
  93.297 +            }
  93.298 +            return new ResizeOption(type, displayName, width, height, showInToolbar, isDefault);
  93.299 +        }
  93.300 +        /**
  93.301 +         * An extra option to size the browser content to fit its window.
  93.302 +         */
  93.303 +        public static final ResizeOption SIZE_TO_FIT = new ResizeOption(Type.CUSTOM, "Size To Fit", -1, -1, true, true);
  93.304 +
  93.305 +        public String getDisplayName() {
  93.306 +            return displayName;
  93.307 +        }
  93.308 +
  93.309 +        public Type getType() {
  93.310 +            return type;
  93.311 +        }
  93.312 +
  93.313 +        public int getWidth() {
  93.314 +            return width;
  93.315 +        }
  93.316 +
  93.317 +        public int getHeight() {
  93.318 +            return height;
  93.319 +        }
  93.320 +
  93.321 +        public boolean isDefault() {
  93.322 +            return isDefault;
  93.323 +        }
  93.324 +
  93.325 +        @Override
  93.326 +        public String toString() {
  93.327 +            return displayName;
  93.328 +        }
  93.329 +
  93.330 +        public String getToolTip() {
  93.331 +            if (width < 0 || height < 0) {
  93.332 +                return displayName;
  93.333 +            }
  93.334 +            StringBuilder sb = new StringBuilder();
  93.335 +            sb.append(width);
  93.336 +            sb.append(" x "); //NOI18N
  93.337 +            sb.append(height);
  93.338 +            sb.append(" ("); //NOI18N
  93.339 +            sb.append(displayName);
  93.340 +            sb.append(')'); //NOI18N
  93.341 +            return sb.toString();
  93.342 +        }
  93.343 +
  93.344 +        @Override
  93.345 +        public boolean equals(Object obj) {
  93.346 +            if (obj == null) {
  93.347 +                return false;
  93.348 +            }
  93.349 +            if (getClass() != obj.getClass()) {
  93.350 +                return false;
  93.351 +            }
  93.352 +            final ResizeOption other = (ResizeOption) obj;
  93.353 +            if (this.type != other.type) {
  93.354 +                return false;
  93.355 +            }
  93.356 +            if ((this.displayName == null) ? (other.displayName != null) : !this.displayName.equals(other.displayName)) {
  93.357 +                return false;
  93.358 +            }
  93.359 +            if (this.width != other.width) {
  93.360 +                return false;
  93.361 +            }
  93.362 +            if (this.height != other.height) {
  93.363 +                return false;
  93.364 +            }
  93.365 +            if (this.isDefault != other.isDefault) {
  93.366 +                return false;
  93.367 +            }
  93.368 +            return true;
  93.369 +        }
  93.370 +
  93.371 +        @Override
  93.372 +        public int hashCode() {
  93.373 +            int hash = 7;
  93.374 +            hash = 11 * hash + (this.type != null ? this.type.hashCode() : 0);
  93.375 +            hash = 11 * hash + (this.displayName != null ? this.displayName.hashCode() : 0);
  93.376 +            hash = 11 * hash + this.width;
  93.377 +            hash = 11 * hash + this.height;
  93.378 +            hash = 11 * hash + (this.isDefault ? 1 : 0);
  93.379 +            return hash;
  93.380 +        }
  93.381 +    }
  93.382 +}
    94.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    94.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Console.java	Mon Oct 07 14:20:58 2013 +0200
    94.3 @@ -0,0 +1,362 @@
    94.4 +/**
    94.5 + * Back 2 Browser Bytecode Translator
    94.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    94.7 + *
    94.8 + * This program is free software: you can redistribute it and/or modify
    94.9 + * it under the terms of the GNU General Public License as published by
   94.10 + * the Free Software Foundation, version 2 of the License.
   94.11 + *
   94.12 + * This program is distributed in the hope that it will be useful,
   94.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   94.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   94.15 + * GNU General Public License for more details.
   94.16 + *
   94.17 + * You should have received a copy of the GNU General Public License
   94.18 + * along with this program. Look for COPYING file in the top folder.
   94.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   94.20 + */
   94.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   94.22 +
   94.23 +import java.io.IOException;
   94.24 +import java.io.InputStream;
   94.25 +import java.io.UnsupportedEncodingException;
   94.26 +import java.lang.reflect.InvocationTargetException;
   94.27 +import java.lang.reflect.Method;
   94.28 +import java.lang.reflect.Modifier;
   94.29 +import java.net.URL;
   94.30 +import java.util.Enumeration;
   94.31 +import netscape.javascript.JSObject;
   94.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   94.33 +
   94.34 +/**
   94.35 + *
   94.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   94.37 + */
   94.38 +public final class Console {
   94.39 +    public Console() {
   94.40 +    }
   94.41 +
   94.42 +    @JavaScriptBody(args = { "elem", "attr" }, body = "return elem[attr].toString();")
   94.43 +    private static native Object getAttr(Object elem, String attr);
   94.44 +
   94.45 +    @JavaScriptBody(args = { "id", "attr", "value" }, body = "window.document.getElementById(id)[attr] = value;")
   94.46 +    private static native void setAttr(String id, String attr, Object value);
   94.47 +
   94.48 +    @JavaScriptBody(args = { "elem", "attr", "value" }, body = "elem[attr] = value;")
   94.49 +    private static native void setAttr(Object id, String attr, Object value);
   94.50 +    
   94.51 +    private static void closeWindow() {}
   94.52 +
   94.53 +    private static Object textArea;
   94.54 +    private static Object statusArea;
   94.55 +    
   94.56 +    private static void log(String newText) {
   94.57 +        if (textArea == null) {
   94.58 +            return;
   94.59 +        }
   94.60 +        String attr = "value";
   94.61 +        setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText);
   94.62 +        setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight"));
   94.63 +    }
   94.64 +    
   94.65 +    private static void beginTest(Case c) {
   94.66 +        Object[] arr = new Object[2];
   94.67 +        beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
   94.68 +        textArea = arr[0];
   94.69 +        statusArea = arr[1];
   94.70 +    }
   94.71 +    
   94.72 +    private static void finishTest(Case c, Object res) {
   94.73 +        if ("null".equals(res)) {
   94.74 +            setAttr(statusArea, "innerHTML", "Success");
   94.75 +        } else {
   94.76 +            setAttr(statusArea, "innerHTML", "Result " + res);
   94.77 +        }
   94.78 +        statusArea = null;
   94.79 +        textArea = null;
   94.80 +    }
   94.81 +
   94.82 +    @JavaScriptBody(args = { "test", "c", "arr" }, body = 
   94.83 +        "var ul = window.document.getElementById('bck2brwsr.result');\n"
   94.84 +        + "var li = window.document.createElement('li');\n"
   94.85 +        + "var span = window.document.createElement('span');"
   94.86 +        + "span.innerHTML = test + ' - ';\n"
   94.87 +        + "var details = window.document.createElement('a');\n"
   94.88 +        + "details.innerHTML = 'Details';\n"
   94.89 +        + "details.href = '#';\n"
   94.90 +        + "var p = window.document.createElement('p');\n"
   94.91 +        + "var status = window.document.createElement('a');\n"
   94.92 +        + "status.innerHTML = 'running';"
   94.93 +        + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n"
   94.94 +        + "status.onclick = function() { c.again(arr); }\n"
   94.95 +        + "var pre = window.document.createElement('textarea');\n"
   94.96 +        + "pre.cols = 100;"
   94.97 +        + "pre.rows = 10;"
   94.98 +        + "li.appendChild(span);\n"
   94.99 +        + "li.appendChild(status);\n"
  94.100 +        + "var span = window.document.createElement('span');"
  94.101 +        + "span.innerHTML = ' ';\n"
  94.102 +        + "li.appendChild(span);\n"
  94.103 +        + "li.appendChild(details);\n"
  94.104 +        + "p.appendChild(pre);\n"
  94.105 +        + "ul.appendChild(li);\n"
  94.106 +        + "arr[0] = pre;\n"
  94.107 +        + "arr[1] = status;\n"
  94.108 +    )
  94.109 +    private static native void beginTest(String test, Case c, Object[] arr);
  94.110 +    
  94.111 +    @JavaScriptBody(args = { "url", "callback", "arr" }, body =
  94.112 +          "var request = new XMLHttpRequest();\n"
  94.113 +        + "request.open('GET', url, true);\n"
  94.114 +        + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
  94.115 +        + "request.onreadystatechange = function() {\n"
  94.116 +        + "  if (this.readyState!==4) return;\n"
  94.117 +        + " try {\n"
  94.118 +        + "  arr[0] = this.responseText;\n"
  94.119 +        + "  callback.run();\n"
  94.120 +        + " } catch (e) { alert(e); }\n"
  94.121 +        + "};\n"
  94.122 +        + "request.send();\n"
  94.123 +    )
  94.124 +    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
  94.125 +    
  94.126 +    public static void runHarness(String url) throws IOException {
  94.127 +        new Console().harness(url);
  94.128 +    }
  94.129 +    
  94.130 +    public void harness(String url) throws IOException {
  94.131 +        log("Connecting to " + url);
  94.132 +        Request r = new Request(url);
  94.133 +    }
  94.134 +    
  94.135 +    private static class Request implements Runnable {
  94.136 +        private final String[] arr = { null };
  94.137 +        private final String url;
  94.138 +        private Case c;
  94.139 +        private int retries;
  94.140 +
  94.141 +        private Request(String url) throws IOException {
  94.142 +            this.url = url;
  94.143 +            loadText(url, new Run(this), arr);
  94.144 +        }
  94.145 +        private Request(String url, String u) throws IOException {
  94.146 +            this.url = url;
  94.147 +            loadText(u, new Run(this), arr);
  94.148 +        }
  94.149 +        
  94.150 +        @Override
  94.151 +        public void run() {
  94.152 +            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
  94.153 +            try {
  94.154 +                if (c == null) {
  94.155 +                    String data = arr[0];
  94.156 +
  94.157 +                    if (data == null) {
  94.158 +                        log("Some error exiting");
  94.159 +                        closeWindow();
  94.160 +                        return;
  94.161 +                    }
  94.162 +
  94.163 +                    if (data.isEmpty()) {
  94.164 +                        log("No data, exiting");
  94.165 +                        closeWindow();
  94.166 +                        return;
  94.167 +                    }
  94.168 +
  94.169 +                    c = Case.parseData(data);
  94.170 +                    beginTest(c);
  94.171 +                    log("Got \"" + data + "\"");
  94.172 +                } else {
  94.173 +                    log("Processing \"" + arr[0] + "\" for " + retries + " time");
  94.174 +                }
  94.175 +                Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest();
  94.176 +                finishTest(c, result);
  94.177 +                
  94.178 +                String u = url + "?request=" + c.getRequestId() + "&result=" + result;
  94.179 +                new Request(url, u);
  94.180 +            } catch (Exception ex) {
  94.181 +                if (ex instanceof InterruptedException) {
  94.182 +                    log("Re-scheduling in 100ms");
  94.183 +                    schedule(new Run(this), 100);
  94.184 +                    return;
  94.185 +                }
  94.186 +                log(ex.getClass().getName() + ":" + ex.getMessage());
  94.187 +            }
  94.188 +        }
  94.189 +    }
  94.190 +    
  94.191 +    private static String encodeURL(String r) throws UnsupportedEncodingException {
  94.192 +        final String SPECIAL = "%$&+,/:;=?@";
  94.193 +        StringBuilder sb = new StringBuilder();
  94.194 +        byte[] utf8 = r.getBytes("UTF-8");
  94.195 +        for (int i = 0; i < utf8.length; i++) {
  94.196 +            int ch = utf8[i] & 0xff;
  94.197 +            if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) {
  94.198 +                final String numbers = "0" + Integer.toHexString(ch);
  94.199 +                sb.append("%").append(numbers.substring(numbers.length() - 2));
  94.200 +            } else {
  94.201 +                if (ch == 32) {
  94.202 +                    sb.append("+");
  94.203 +                } else {
  94.204 +                    sb.append((char)ch);
  94.205 +                }
  94.206 +            }
  94.207 +        }
  94.208 +        return sb.toString();
  94.209 +    }
  94.210 +    
  94.211 +    static String invoke(String clazz, String method) throws 
  94.212 +    ClassNotFoundException, InvocationTargetException, IllegalAccessException, 
  94.213 +    InstantiationException, InterruptedException {
  94.214 +        final Object r = new Case(null).invokeMethod(clazz, method);
  94.215 +        return r == null ? "null" : r.toString().toString();
  94.216 +    }
  94.217 +
  94.218 +    /** Helper method that inspects the classpath and loads given resource
  94.219 +     * (usually a class file). Used while running tests in Rhino.
  94.220 +     * 
  94.221 +     * @param name resource name to find
  94.222 +     * @return the array of bytes in the given resource
  94.223 +     * @throws IOException I/O in case something goes wrong
  94.224 +     */
  94.225 +    public static byte[] read(String name) throws IOException {
  94.226 +        URL u = null;
  94.227 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
  94.228 +        while (en.hasMoreElements()) {
  94.229 +            u = en.nextElement();
  94.230 +        }
  94.231 +        if (u == null) {
  94.232 +            throw new IOException("Can't find " + name);
  94.233 +        }
  94.234 +        InputStream is = null;
  94.235 +        try {
  94.236 +            is = u.openStream();
  94.237 +            byte[] arr;
  94.238 +            arr = new byte[is.available()];
  94.239 +            int offset = 0;
  94.240 +            while (offset < arr.length) {
  94.241 +                int len = is.read(arr, offset, arr.length - offset);
  94.242 +                if (len == -1) {
  94.243 +                    throw new IOException("Can't read " + name);
  94.244 +                }
  94.245 +                offset += len;
  94.246 +            }
  94.247 +            return arr;
  94.248 +        } finally {
  94.249 +            if (is != null) is.close();
  94.250 +        }
  94.251 +    }
  94.252 +   
  94.253 +    private static void turnAssetionStatusOn() {
  94.254 +    }
  94.255 +
  94.256 +    @JavaScriptBody(args = { "r", "time" }, body = "return window.setTimeout(function() { r.run(); }, time);")
  94.257 +    private static native Object schedule(Runnable r, int time);
  94.258 +    
  94.259 +    private static final class Case {
  94.260 +        private final Object data;
  94.261 +        private Object inst;
  94.262 +
  94.263 +        private Case(Object data) {
  94.264 +            this.data = data;
  94.265 +        }
  94.266 +        
  94.267 +        public static Case parseData(String s) {
  94.268 +            return new Case(toJSON(s));
  94.269 +        }
  94.270 +        
  94.271 +        public String getMethodName() {
  94.272 +            return (String) value("methodName", data);
  94.273 +        }
  94.274 +
  94.275 +        public String getClassName() {
  94.276 +            return (String) value("className", data);
  94.277 +        }
  94.278 +        
  94.279 +        public int getRequestId() {
  94.280 +            Object v = value("request", data);
  94.281 +            if (v instanceof Number) {
  94.282 +                return ((Number)v).intValue();
  94.283 +            }
  94.284 +            return Integer.parseInt(v.toString());
  94.285 +        }
  94.286 +
  94.287 +        public String getHtmlFragment() {
  94.288 +            return (String) value("html", data);
  94.289 +        }
  94.290 +        
  94.291 +        void again(Object[] arr) {
  94.292 +            try {
  94.293 +                textArea = arr[0];
  94.294 +                statusArea = arr[1];
  94.295 +                setAttr(textArea, "value", "");
  94.296 +                runTest();
  94.297 +            } catch (Exception ex) {
  94.298 +                log(ex.getClass().getName() + ":" + ex.getMessage());
  94.299 +            }
  94.300 +        }
  94.301 +
  94.302 +        private Object runTest() throws IllegalAccessException, 
  94.303 +        IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, 
  94.304 +        InvocationTargetException, InstantiationException, InterruptedException {
  94.305 +            if (this.getHtmlFragment() != null) {
  94.306 +                setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment());
  94.307 +            }
  94.308 +            log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId());
  94.309 +            Object result = invokeMethod(this.getClassName(), this.getMethodName());
  94.310 +            setAttr("bck2brwsr.fragment", "innerHTML", "");
  94.311 +            log("Result: " + result);
  94.312 +            result = encodeURL("" + result);
  94.313 +            log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result);
  94.314 +            return result;
  94.315 +        }
  94.316 +
  94.317 +        private Object invokeMethod(String clazz, String method)
  94.318 +        throws ClassNotFoundException, InvocationTargetException,
  94.319 +        InterruptedException, IllegalAccessException, IllegalArgumentException,
  94.320 +        InstantiationException {
  94.321 +            Method found = null;
  94.322 +            Class<?> c = Class.forName(clazz);
  94.323 +            for (Method m : c.getMethods()) {
  94.324 +                if (m.getName().equals(method)) {
  94.325 +                    found = m;
  94.326 +                }
  94.327 +            }
  94.328 +            Object res;
  94.329 +            if (found != null) {
  94.330 +                try {
  94.331 +                    if ((found.getModifiers() & Modifier.STATIC) != 0) {
  94.332 +                        res = found.invoke(null);
  94.333 +                    } else {
  94.334 +                        if (inst == null) {
  94.335 +                            inst = c.newInstance();
  94.336 +                        }
  94.337 +                        res = found.invoke(inst);
  94.338 +                    }
  94.339 +                } catch (Throwable ex) {
  94.340 +                    if (ex instanceof InvocationTargetException) {
  94.341 +                        ex = ((InvocationTargetException) ex).getTargetException();
  94.342 +                    }
  94.343 +                    if (ex instanceof InterruptedException) {
  94.344 +                        throw (InterruptedException)ex;
  94.345 +                    }
  94.346 +                    res = ex.getClass().getName() + ":" + ex.getMessage();
  94.347 +                }
  94.348 +            } else {
  94.349 +                res = "Can't find method " + method + " in " + clazz;
  94.350 +            }
  94.351 +            return res;
  94.352 +        }
  94.353 +
  94.354 +        @JavaScriptBody(args = { "s" }, body = "return eval('(' + s + ')');")
  94.355 +        private static native Object toJSON(String s);
  94.356 +        
  94.357 +        private static Object value(String p, Object d) {
  94.358 +            return ((JSObject)d).getMember(p);
  94.359 +        }
  94.360 +    }
  94.361 +    
  94.362 +    static {
  94.363 +        turnAssetionStatusOn();
  94.364 +    }
  94.365 +}
    95.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    95.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXBrwsr.java	Mon Oct 07 14:20:58 2013 +0200
    95.3 @@ -0,0 +1,177 @@
    95.4 +/**
    95.5 + * Back 2 Browser Bytecode Translator
    95.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    95.7 + *
    95.8 + * This program is free software: you can redistribute it and/or modify
    95.9 + * it under the terms of the GNU General Public License as published by
   95.10 + * the Free Software Foundation, version 2 of the License.
   95.11 + *
   95.12 + * This program is distributed in the hope that it will be useful,
   95.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   95.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   95.15 + * GNU General Public License for more details.
   95.16 + *
   95.17 + * You should have received a copy of the GNU General Public License
   95.18 + * along with this program. Look for COPYING file in the top folder.
   95.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   95.20 + */
   95.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   95.22 +
   95.23 +import java.util.List;
   95.24 +import java.util.TooManyListenersException;
   95.25 +import java.util.logging.Level;
   95.26 +import java.util.logging.Logger;
   95.27 +import javafx.application.Application;
   95.28 +import javafx.application.Platform;
   95.29 +import javafx.beans.value.ChangeListener;
   95.30 +import javafx.beans.value.ObservableValue;
   95.31 +import javafx.event.ActionEvent;
   95.32 +import javafx.event.EventHandler;
   95.33 +import javafx.geometry.Insets;
   95.34 +import javafx.geometry.Pos;
   95.35 +import javafx.scene.Scene;
   95.36 +import javafx.scene.control.Button;
   95.37 +import javafx.scene.control.ToolBar;
   95.38 +import javafx.scene.layout.BorderPane;
   95.39 +import javafx.scene.layout.HBox;
   95.40 +import javafx.scene.layout.VBox;
   95.41 +import javafx.scene.text.Text;
   95.42 +import javafx.scene.web.WebEngine;
   95.43 +import javafx.scene.web.WebEvent;
   95.44 +import javafx.scene.web.WebView;
   95.45 +import javafx.stage.Modality;
   95.46 +import javafx.stage.Stage;
   95.47 +import netscape.javascript.JSObject;
   95.48 +
   95.49 +/**
   95.50 + * Demonstrates a WebView object accessing a web page.
   95.51 + *
   95.52 + * @see javafx.scene.web.WebView
   95.53 + * @see javafx.scene.web.WebEngine
   95.54 + */
   95.55 +public class FXBrwsr extends Application {
   95.56 +    private static final Logger LOG = Logger.getLogger(FXBrwsr.class.getName());
   95.57 +    
   95.58 +    @Override
   95.59 +    public void start(Stage primaryStage) throws Exception {
   95.60 +        WebView view = new WebView();
   95.61 +        WebController wc = new WebController(view, getParameters().getUnnamed());
   95.62 +        
   95.63 +        FXInspect.initialize(view.getEngine());
   95.64 +
   95.65 +        final VBox vbox = new VBox();
   95.66 +        vbox.setAlignment( Pos.CENTER );
   95.67 +        vbox.setStyle( "-fx-background-color: #808080;");
   95.68 +
   95.69 +
   95.70 +        HBox hbox = new HBox();
   95.71 +        hbox.setStyle( "-fx-background-color: #808080;");
   95.72 +        hbox.setAlignment(Pos.CENTER);
   95.73 +        hbox.getChildren().add(vbox);
   95.74 +        vbox.getChildren().add(view);
   95.75 +
   95.76 +        BorderPane root = new BorderPane();
   95.77 +        final boolean showToolbar = "true".equals(this.getParameters().getNamed().get("toolbar")); // NOI18N
   95.78 +        final boolean useFirebug = "true".equals(this.getParameters().getNamed().get("firebug")); // NOI18N
   95.79 +        if (showToolbar) {
   95.80 +            final ToolBar toolbar = new BrowserToolbar(view, vbox, useFirebug);
   95.81 +            root.setTop( toolbar );
   95.82 +        }
   95.83 +        root.setCenter(hbox);
   95.84 +
   95.85 +        Scene scene = new Scene(root, 800, 600);
   95.86 +
   95.87 +        primaryStage.setTitle( "Device Emulator" );
   95.88 +        primaryStage.setScene( scene );
   95.89 +        primaryStage.show();
   95.90 +    }
   95.91 +    
   95.92 +    /**
   95.93 +     * Create a resizable WebView pane
   95.94 +     */
   95.95 +    private static class WebController {
   95.96 +        private final JVMBridge bridge;
   95.97 +
   95.98 +        public WebController(WebView view, List<String> params) {
   95.99 +            this.bridge = new JVMBridge(view.getEngine());
  95.100 +            LOG.log(Level.INFO, "Initializing WebView with {0}", params);
  95.101 +            final WebEngine eng = view.getEngine();
  95.102 +            try {
  95.103 +                JVMBridge.addBck2BrwsrLoad(new InitBck2Brwsr(eng));
  95.104 +            } catch (TooManyListenersException ex) {
  95.105 +                LOG.log(Level.SEVERE, null, ex);
  95.106 +            }
  95.107 +            
  95.108 +            if (params.size() > 0) {
  95.109 +                LOG.log(Level.INFO, "loading page {0}", params.get(0));
  95.110 +                eng.load(params.get(0));
  95.111 +                LOG.fine("back from load");
  95.112 +            }
  95.113 +            eng.setOnAlert(new EventHandler<WebEvent<String>>() {
  95.114 +                @Override
  95.115 +                public void handle(WebEvent<String> t) {
  95.116 +                    final Stage dialogStage = new Stage();
  95.117 +                    dialogStage.initModality(Modality.WINDOW_MODAL);
  95.118 +                    dialogStage.setTitle("Warning");
  95.119 +                    final Button button = new Button("Close");
  95.120 +                    final Text text = new Text(t.getData());
  95.121 +                    
  95.122 +                    VBox box = new VBox();
  95.123 +                    box.setAlignment(Pos.CENTER);
  95.124 +                    box.setSpacing(10);
  95.125 +                    box.setPadding(new Insets(10));
  95.126 +                    box.getChildren().addAll(text, button);
  95.127 +                    
  95.128 +                    dialogStage.setScene(new Scene(box));
  95.129 +                    
  95.130 +                    button.setCancelButton(true);
  95.131 +                    button.setOnAction(new EventHandler<ActionEvent>() {
  95.132 +                        @Override
  95.133 +                        public void handle(ActionEvent t) {
  95.134 +                            dialogStage.close();
  95.135 +                        }
  95.136 +                    });
  95.137 +                    
  95.138 +                    dialogStage.centerOnScreen();
  95.139 +                    dialogStage.showAndWait();
  95.140 +                }
  95.141 +            });
  95.142 +        }
  95.143 +
  95.144 +        boolean initBck2Brwsr(WebEngine webEngine) {
  95.145 +            JSObject jsobj = (JSObject) webEngine.executeScript("window");
  95.146 +            LOG.log(Level.FINE, "window: {0}", jsobj);
  95.147 +            Object prev = jsobj.getMember("bck2brwsr");
  95.148 +            if ("undefined".equals(prev)) {
  95.149 +                jsobj.setMember("bck2brwsr", bridge);
  95.150 +                return true;
  95.151 +            }
  95.152 +            return false;
  95.153 +        }
  95.154 +
  95.155 +        private class InitBck2Brwsr implements ChangeListener<Void>, Runnable {
  95.156 +            private final WebEngine eng;
  95.157 +
  95.158 +            public InitBck2Brwsr(WebEngine eng) {
  95.159 +                this.eng = eng;
  95.160 +            }
  95.161 +
  95.162 +            @Override
  95.163 +            public synchronized void changed(ObservableValue<? extends Void> ov, Void t, Void t1) {
  95.164 +                Platform.runLater(this);
  95.165 +                try {
  95.166 +                    wait();
  95.167 +                } catch (InterruptedException ex) {
  95.168 +                    LOG.log(Level.SEVERE, null, ex);
  95.169 +                }
  95.170 +            }
  95.171 +
  95.172 +            @Override
  95.173 +            public synchronized void run() {
  95.174 +                initBck2Brwsr(eng);
  95.175 +                notifyAll();
  95.176 +            }
  95.177 +        }
  95.178 +    }
  95.179 +    
  95.180 +}
    96.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    96.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/FXInspect.java	Mon Oct 07 14:20:58 2013 +0200
    96.3 @@ -0,0 +1,112 @@
    96.4 +/**
    96.5 + * Back 2 Browser Bytecode Translator
    96.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    96.7 + *
    96.8 + * This program is free software: you can redistribute it and/or modify
    96.9 + * it under the terms of the GNU General Public License as published by
   96.10 + * the Free Software Foundation, version 2 of the License.
   96.11 + *
   96.12 + * This program is distributed in the hope that it will be useful,
   96.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   96.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   96.15 + * GNU General Public License for more details.
   96.16 + *
   96.17 + * You should have received a copy of the GNU General Public License
   96.18 + * along with this program. Look for COPYING file in the top folder.
   96.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   96.20 + */
   96.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   96.22 +
   96.23 +import com.sun.javafx.scene.web.Debugger;
   96.24 +import java.io.IOException;
   96.25 +import java.io.ObjectInputStream;
   96.26 +import java.io.ObjectOutputStream;
   96.27 +import java.net.InetAddress;
   96.28 +import java.net.Socket;
   96.29 +import java.nio.charset.StandardCharsets;
   96.30 +import java.util.logging.Level;
   96.31 +import java.util.logging.Logger;
   96.32 +import javafx.application.Platform;
   96.33 +import javafx.scene.web.WebEngine;
   96.34 +import javafx.util.Callback;
   96.35 +import org.openide.util.Exceptions;
   96.36 +
   96.37 +/**
   96.38 + *
   96.39 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   96.40 + */
   96.41 +final class FXInspect implements Runnable {
   96.42 +    private static final Logger LOG = Logger.getLogger(FXInspect.class.getName());
   96.43 +    
   96.44 +    
   96.45 +    private final WebEngine engine;
   96.46 +    private final ObjectInputStream input;
   96.47 +    
   96.48 +    private FXInspect(WebEngine engine, int port) throws IOException {
   96.49 +        this.engine = engine;
   96.50 +        
   96.51 +        Socket socket = new Socket(InetAddress.getByName(null), port);
   96.52 +        ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
   96.53 +        this.input = new ObjectInputStream(socket.getInputStream());
   96.54 +        initializeDebugger(output);
   96.55 +    }
   96.56 +    
   96.57 +    static boolean initialize(WebEngine engine) {
   96.58 +        final int inspectPort = Integer.getInteger("netbeans.inspect.port", -1); // NOI18N
   96.59 +        if (inspectPort != -1) {
   96.60 +            try {
   96.61 +                FXInspect inspector = new FXInspect(engine, inspectPort);
   96.62 +                Thread t = new Thread(inspector, "FX<->NetBeans Inspector");
   96.63 +                t.start();
   96.64 +                return true;
   96.65 +            } catch (IOException ex) {
   96.66 +                LOG.log(Level.INFO, "Cannot connect to NetBeans IDE to port " + inspectPort, ex); // NOI18N
   96.67 +            }
   96.68 +        }
   96.69 +        return false;
   96.70 +    }
   96.71 +    
   96.72 +    private void initializeDebugger(final ObjectOutputStream output) {
   96.73 +        Platform.runLater(new Runnable() {
   96.74 +            @Override
   96.75 +            public void run() {
   96.76 +                Debugger debugger = engine.impl_getDebugger();
   96.77 +                debugger.setEnabled(true);
   96.78 +                debugger.setMessageCallback(new Callback<String,Void>() {
   96.79 +                    @Override
   96.80 +                    public Void call(String message) {
   96.81 +                        try {
   96.82 +                            byte[] bytes = message.getBytes(StandardCharsets.UTF_8);
   96.83 +                            output.writeInt(bytes.length);
   96.84 +                            output.write(bytes);
   96.85 +                            output.flush();
   96.86 +                        } catch (IOException ioex) {
   96.87 +                            ioex.printStackTrace();
   96.88 +                        }
   96.89 +                        return null;
   96.90 +                    }
   96.91 +                });
   96.92 +            }
   96.93 +        });
   96.94 +    }
   96.95 +
   96.96 +    @Override
   96.97 +    public void run() {
   96.98 +        try {
   96.99 +            while (true) {
  96.100 +                int length = input.readInt();
  96.101 +                byte[] bytes = new byte[length];
  96.102 +                input.readFully(bytes);
  96.103 +                final String message = new String(bytes, StandardCharsets.UTF_8);
  96.104 +                Platform.runLater(new Runnable() {
  96.105 +                    @Override
  96.106 +                    public void run() {
  96.107 +                        engine.impl_getDebugger().sendMessage(message);
  96.108 +                    }
  96.109 +                });
  96.110 +            }
  96.111 +        } catch (IOException ioex) {
  96.112 +            ioex.printStackTrace();
  96.113 +        }
  96.114 +    }
  96.115 +}
    97.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    97.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/JVMBridge.java	Mon Oct 07 14:20:58 2013 +0200
    97.3 @@ -0,0 +1,152 @@
    97.4 +/**
    97.5 + * Back 2 Browser Bytecode Translator
    97.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    97.7 + *
    97.8 + * This program is free software: you can redistribute it and/or modify
    97.9 + * it under the terms of the GNU General Public License as published by
   97.10 + * the Free Software Foundation, version 2 of the License.
   97.11 + *
   97.12 + * This program is distributed in the hope that it will be useful,
   97.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   97.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   97.15 + * GNU General Public License for more details.
   97.16 + *
   97.17 + * You should have received a copy of the GNU General Public License
   97.18 + * along with this program. Look for COPYING file in the top folder.
   97.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   97.20 + */
   97.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
   97.22 +
   97.23 +import java.io.BufferedReader;
   97.24 +import java.io.Reader;
   97.25 +import org.apidesign.html.boot.spi.Fn;
   97.26 +import java.net.URL;
   97.27 +import java.util.ArrayList;
   97.28 +import java.util.Arrays;
   97.29 +import java.util.Collection;
   97.30 +import java.util.List;
   97.31 +import java.util.TooManyListenersException;
   97.32 +import javafx.beans.value.ChangeListener;
   97.33 +import javafx.scene.web.WebEngine;
   97.34 +import netscape.javascript.JSObject;
   97.35 +import org.apidesign.html.boot.impl.FindResources;
   97.36 +import org.apidesign.html.boot.impl.FnUtils;
   97.37 +
   97.38 +/**
   97.39 + *
   97.40 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   97.41 + */
   97.42 +public final class JVMBridge {
   97.43 +    private final WebEngine engine;
   97.44 +    private final ClassLoader cl;
   97.45 +    private final WebPresenter presenter;
   97.46 +    
   97.47 +    private static ClassLoader[] ldrs;
   97.48 +    private static ChangeListener<Void> onBck2BrwsrLoad;
   97.49 +    
   97.50 +    JVMBridge(WebEngine eng) {
   97.51 +        this.engine = eng;
   97.52 +        final ClassLoader p = JVMBridge.class.getClassLoader().getParent();
   97.53 +        this.presenter = new WebPresenter();
   97.54 +        this.cl = FnUtils.newLoader(presenter, presenter, p);
   97.55 +    }
   97.56 +        
   97.57 +    public static void registerClassLoaders(ClassLoader[] loaders) {
   97.58 +        ldrs = loaders.clone();
   97.59 +    }
   97.60 +    
   97.61 +    public static void addBck2BrwsrLoad(ChangeListener<Void> l) throws TooManyListenersException {
   97.62 +        if (onBck2BrwsrLoad != null) {
   97.63 +            throw new TooManyListenersException();
   97.64 +        }
   97.65 +        onBck2BrwsrLoad = l;
   97.66 +    }
   97.67 +
   97.68 +    public static void onBck2BrwsrLoad() {
   97.69 +        ChangeListener<Void> l = onBck2BrwsrLoad;
   97.70 +        if (l != null) {
   97.71 +            l.changed(null, null, null);
   97.72 +        }
   97.73 +    }
   97.74 +    
   97.75 +    public Class<?> loadClass(String name) throws ClassNotFoundException {
   97.76 +        FnUtils.currentPresenter(presenter);
   97.77 +        return Class.forName(name, true, cl);
   97.78 +    }
   97.79 +    
   97.80 +    private final class WebPresenter implements FindResources, Fn.Presenter {
   97.81 +        @Override
   97.82 +        public void findResources(String name, Collection<? super URL> results, boolean oneIsEnough) {
   97.83 +            if (ldrs != null) for (ClassLoader l : ldrs) {
   97.84 +                URL u = l.getResource(name);
   97.85 +                if (u != null) {
   97.86 +                    results.add(u);
   97.87 +                }
   97.88 +            }
   97.89 +        }
   97.90 +
   97.91 +        @Override
   97.92 +        public Fn defineFn(String code, String... names) {
   97.93 +            StringBuilder sb = new StringBuilder();
   97.94 +            sb.append("(function() {");
   97.95 +            sb.append("  return function(");
   97.96 +            String sep = "";
   97.97 +            for (String n : names) {
   97.98 +                sb.append(sep).append(n);
   97.99 +                sep = ",";
  97.100 +            }
  97.101 +            sb.append(") {\n");
  97.102 +            sb.append(code);
  97.103 +            sb.append("};");
  97.104 +            sb.append("})()");
  97.105 +            
  97.106 +            JSObject x = (JSObject) engine.executeScript(sb.toString());
  97.107 +            return new JSFn(this, x);
  97.108 +        }
  97.109 +
  97.110 +        @Override
  97.111 +        public void displayPage(URL page, Runnable onPageLoad) {
  97.112 +            throw new UnsupportedOperationException("Not supported yet.");
  97.113 +        }
  97.114 +
  97.115 +        @Override
  97.116 +        public void loadScript(Reader code) throws Exception {
  97.117 +            BufferedReader r = new BufferedReader(code);
  97.118 +            StringBuilder sb = new StringBuilder();
  97.119 +            for (;;) {
  97.120 +                String l = r.readLine();
  97.121 +                if (l == null) {
  97.122 +                    break;
  97.123 +                }
  97.124 +                sb.append(l).append('\n');
  97.125 +            }
  97.126 +            engine.executeScript(sb.toString());
  97.127 +        }
  97.128 +    }
  97.129 +    
  97.130 +    private static final class JSFn extends Fn {
  97.131 +        private final JSObject fn;
  97.132 +
  97.133 +        private JSFn(WebPresenter cl, JSObject fn) {
  97.134 +            super(cl);
  97.135 +            this.fn = fn;
  97.136 +        }
  97.137 +
  97.138 +        @Override
  97.139 +        public Object invoke(Object thiz, Object... args) throws Exception {
  97.140 +            try {
  97.141 +                List<Object> all = new ArrayList<Object>(args.length + 1);
  97.142 +                all.add(thiz == null ? fn : thiz);
  97.143 +                all.addAll(Arrays.asList(args));
  97.144 +                Object ret = fn.call("call", all.toArray()); // NOI18N
  97.145 +                return ret == fn ? null : ret;
  97.146 +            } catch (Error t) {
  97.147 +                t.printStackTrace();
  97.148 +                throw t;
  97.149 +            } catch (Exception t) {
  97.150 +                t.printStackTrace();
  97.151 +                throw t;
  97.152 +            }
  97.153 +        }
  97.154 +    }
  97.155 +}
    98.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    98.2 +++ b/launcher/fx/src/main/java/org/apidesign/bck2brwsr/launcher/fximpl/Run.java	Mon Oct 07 14:20:58 2013 +0200
    98.3 @@ -0,0 +1,35 @@
    98.4 +/**
    98.5 + * Back 2 Browser Bytecode Translator
    98.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    98.7 + *
    98.8 + * This program is free software: you can redistribute it and/or modify
    98.9 + * it under the terms of the GNU General Public License as published by
   98.10 + * the Free Software Foundation, version 2 of the License.
   98.11 + *
   98.12 + * This program is distributed in the hope that it will be useful,
   98.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   98.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   98.15 + * GNU General Public License for more details.
   98.16 + *
   98.17 + * You should have received a copy of the GNU General Public License
   98.18 + * along with this program. Look for COPYING file in the top folder.
   98.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
   98.20 + */
   98.21 +
   98.22 +package org.apidesign.bck2brwsr.launcher.fximpl;
   98.23 +
   98.24 +/**
   98.25 + *
   98.26 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   98.27 + */
   98.28 +public final class Run implements Runnable {
   98.29 +    private final Runnable r;
   98.30 +    Run(Runnable r) {
   98.31 +        this.r = r;
   98.32 +    }
   98.33 +
   98.34 +    @Override
   98.35 +    public void run() {
   98.36 +        r.run();
   98.37 +    }
   98.38 +}
    99.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/desktop.png has changed
   100.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/firebug.png has changed
   101.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldLandscape.png has changed
   102.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/handheldPortrait.png has changed
   103.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   103.2 +++ b/launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/harness.xhtml	Mon Oct 07 14:20:58 2013 +0200
   103.3 @@ -0,0 +1,52 @@
   103.4 +<?xml version="1.0" encoding="UTF-8"?>
   103.5 +<!--
   103.6 +
   103.7 +    Back 2 Browser Bytecode Translator
   103.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   103.9 +
  103.10 +    This program is free software: you can redistribute it and/or modify
  103.11 +    it under the terms of the GNU General Public License as published by
  103.12 +    the Free Software Foundation, version 2 of the License.
  103.13 +
  103.14 +    This program is distributed in the hope that it will be useful,
  103.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
  103.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  103.17 +    GNU General Public License for more details.
  103.18 +
  103.19 +    You should have received a copy of the GNU General Public License
  103.20 +    along with this program. Look for COPYING file in the top folder.
  103.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
  103.22 +
  103.23 +-->
  103.24 +<!DOCTYPE html>
  103.25 +<html xmlns="http://www.w3.org/1999/xhtml">
  103.26 +    <head>
  103.27 +        <title>Bck2Brwsr Harness</title>
  103.28 +    </head>
  103.29 +    <body>
  103.30 +        <script src="/bck2brwsr.js"></script>
  103.31 +        <script>
  103.32 +            var vm = bck2brwsr();
  103.33 +        </script>
  103.34 +        
  103.35 +        <h1>Bck2Brwsr Execution Harness</h1>
  103.36 +        
  103.37 +        <ul id="bck2brwsr.result" style="width: 100%;" >
  103.38 +        </ul>
  103.39 +
  103.40 +        <div id="bck2brwsr.fragment"/>
  103.41 +        
  103.42 +        <script type="text/javascript">
  103.43 +            try {
  103.44 +                (function() {
  103.45 +                    var cls = vm.loadClass('org.apidesign.bck2brwsr.launcher.fximpl.Console');
  103.46 +                    // fxbrwsr mangling
  103.47 +                    var inst = cls.newInstance();
  103.48 +                    inst.harness('$U/../data');
  103.49 +                })();
  103.50 +            } catch (err) { 
  103.51 +                alert('Error executing harness: ' + err); 
  103.52 +            }
  103.53 +        </script>
  103.54 +    </body>
  103.55 +</html>
   104.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/netbook.png has changed
   105.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/selectionMode.png has changed
   106.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/sizeToFit.png has changed
   107.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletLandscape.png has changed
   108.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/tabletPortrait.png has changed
   109.1 Binary file launcher/fx/src/main/resources/org/apidesign/bck2brwsr/launcher/fximpl/widescreen.png has changed
   110.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   110.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsClassLoaderTest.java	Mon Oct 07 14:20:58 2013 +0200
   110.3 @@ -0,0 +1,182 @@
   110.4 +/**
   110.5 + * Back 2 Browser Bytecode Translator
   110.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   110.7 + *
   110.8 + * This program is free software: you can redistribute it and/or modify
   110.9 + * it under the terms of the GNU General Public License as published by
  110.10 + * the Free Software Foundation, version 2 of the License.
  110.11 + *
  110.12 + * This program is distributed in the hope that it will be useful,
  110.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  110.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  110.15 + * GNU General Public License for more details.
  110.16 + *
  110.17 + * You should have received a copy of the GNU General Public License
  110.18 + * along with this program. Look for COPYING file in the top folder.
  110.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  110.20 + */
  110.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
  110.22 +
  110.23 +import java.io.Reader;
  110.24 +import java.lang.reflect.InvocationTargetException;
  110.25 +import java.lang.reflect.Method;
  110.26 +import java.net.URL;
  110.27 +import java.net.URLClassLoader;
  110.28 +import java.util.ArrayList;
  110.29 +import java.util.Arrays;
  110.30 +import java.util.Collection;
  110.31 +import java.util.List;
  110.32 +import javax.script.Invocable;
  110.33 +import javax.script.ScriptEngine;
  110.34 +import javax.script.ScriptEngineManager;
  110.35 +import javax.script.ScriptException;
  110.36 +import org.apidesign.html.boot.spi.Fn;
  110.37 +import org.apidesign.html.boot.impl.FindResources;
  110.38 +import org.apidesign.html.boot.impl.FnUtils;
  110.39 +import static org.testng.Assert.*;
  110.40 +import org.testng.annotations.BeforeClass;
  110.41 +import org.testng.annotations.BeforeMethod;
  110.42 +import org.testng.annotations.Test;
  110.43 +
  110.44 +/**
  110.45 + *
  110.46 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  110.47 + */
  110.48 +public class JsClassLoaderTest {
  110.49 +    private static ClassLoader loader;
  110.50 +    private static Class<?> methodClass;
  110.51 +    private static Fn.Presenter presenter;
  110.52 +    
  110.53 +    public JsClassLoaderTest() {
  110.54 +    }
  110.55 +
  110.56 +    @BeforeClass
  110.57 +    public static void setUpClass() throws Exception {
  110.58 +        ScriptEngineManager sem = new ScriptEngineManager();
  110.59 +        final ScriptEngine eng = sem.getEngineByMimeType("text/javascript");
  110.60 +        
  110.61 +        final URL my = JsClassLoaderTest.class.getProtectionDomain().getCodeSource().getLocation();
  110.62 +        ClassLoader parent = JsClassLoaderTest.class.getClassLoader().getParent();
  110.63 +        final URLClassLoader ul = new URLClassLoader(new URL[] { my }, parent);
  110.64 +        class Fr implements FindResources, Fn.Presenter {
  110.65 +            @Override
  110.66 +            public void findResources(String path, Collection<? super URL> results, boolean oneIsEnough) {
  110.67 +                URL u = ul.getResource(path);
  110.68 +                if (u != null) {
  110.69 +                    results.add(u);
  110.70 +                }
  110.71 +            }
  110.72 +
  110.73 +            @Override
  110.74 +            public Fn defineFn(String code, String... names) {
  110.75 +                StringBuilder sb = new StringBuilder();
  110.76 +                sb.append("(function() {");
  110.77 +                sb.append("return function(");
  110.78 +                String sep = "";
  110.79 +                for (String n : names) {
  110.80 +                    sb.append(sep);
  110.81 +                    sb.append(n);
  110.82 +                    sep = ", ";
  110.83 +                }
  110.84 +                sb.append(") {");
  110.85 +                sb.append(code);
  110.86 +                sb.append("};");
  110.87 +                sb.append("})()");
  110.88 +                try {
  110.89 +                    final Object val = eng.eval(sb.toString());
  110.90 +                    return new Fn(this) {
  110.91 +                        @Override
  110.92 +                        public Object invoke(Object thiz, Object... args) throws Exception {
  110.93 +                            List<Object> all = new ArrayList<Object>(args.length + 1);
  110.94 +                            all.add(thiz == null ? val : thiz);
  110.95 +                            all.addAll(Arrays.asList(args));
  110.96 +                            Invocable inv = (Invocable)eng;
  110.97 +                            Object ret = inv.invokeMethod(val, "call", all.toArray());
  110.98 +                            return ret == val ? null : ret;
  110.99 +                        }
 110.100 +                    };
 110.101 +                } catch (ScriptException ex) {
 110.102 +                    throw new LinkageError("Can't parse: " + sb, ex);
 110.103 +                }
 110.104 +            }
 110.105 +
 110.106 +            @Override
 110.107 +            public void displayPage(URL page, Runnable onPageLoad) {
 110.108 +                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 110.109 +            }
 110.110 +
 110.111 +            @Override
 110.112 +            public void loadScript(Reader code) throws Exception {
 110.113 +                throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 110.114 +            }
 110.115 +        }
 110.116 +        
 110.117 +        Fr fr = new Fr();
 110.118 +        presenter = fr;
 110.119 +        loader = FnUtils.newLoader(fr, fr, parent);
 110.120 +        methodClass = loader.loadClass(JsMethods.class.getName());
 110.121 +    }
 110.122 +    
 110.123 +    @BeforeMethod public void registerPresenter() {
 110.124 +        FnUtils.currentPresenter(presenter);
 110.125 +    }
 110.126 +    
 110.127 +    @Test public void noParamMethod() throws Throwable {
 110.128 +        Method plus = methodClass.getMethod("fortyTwo");
 110.129 +        try {
 110.130 +            final Object val = plus.invoke(null);
 110.131 +            assertTrue(val instanceof Number, "A number returned " + val);
 110.132 +            assertEquals(((Number)val).intValue(), 42);
 110.133 +        } catch (InvocationTargetException ex) {
 110.134 +            throw ex.getTargetException();
 110.135 +        }
 110.136 +    }
 110.137 +    
 110.138 +    @Test public void testExecuteScript() throws Throwable {
 110.139 +        Method plus = methodClass.getMethod("plus", int.class, int.class);
 110.140 +        try {
 110.141 +            assertEquals(plus.invoke(null, 10, 20), 30);
 110.142 +        } catch (InvocationTargetException ex) {
 110.143 +            throw ex.getTargetException();
 110.144 +        }
 110.145 +    }
 110.146 +
 110.147 +    @Test public void overloadedMethod() throws Throwable {
 110.148 +        Method plus = methodClass.getMethod("plus", int.class);
 110.149 +        try {
 110.150 +            assertEquals(plus.invoke(null, 10), 10);
 110.151 +        } catch (InvocationTargetException ex) {
 110.152 +            throw ex.getTargetException();
 110.153 +        }
 110.154 +    }
 110.155 +    
 110.156 +    @Test public void instanceMethod() throws Throwable {
 110.157 +        Method plus = methodClass.getMethod("plusInst", int.class);
 110.158 +        Object inst = methodClass.newInstance();
 110.159 +        try {
 110.160 +            assertEquals(plus.invoke(inst, 10), 10);
 110.161 +        } catch (InvocationTargetException ex) {
 110.162 +            throw ex.getTargetException();
 110.163 +        }
 110.164 +    }
 110.165 +    
 110.166 +    @Test public void staticThis() throws Throwable {
 110.167 +        Method st = methodClass.getMethod("staticThis");
 110.168 +        try {
 110.169 +            assertNull(st.invoke(null));
 110.170 +        } catch (InvocationTargetException ex) {
 110.171 +            throw ex.getTargetException();
 110.172 +        }
 110.173 +    }
 110.174 +
 110.175 +    @Test public void getThis() throws Throwable {
 110.176 +        Object th = methodClass.newInstance();
 110.177 +        Method st = methodClass.getMethod("getThis");
 110.178 +        try {
 110.179 +            assertEquals(st.invoke(th), th);
 110.180 +        } catch (InvocationTargetException ex) {
 110.181 +            throw ex.getTargetException();
 110.182 +        }
 110.183 +    }
 110.184 +    
 110.185 +}
 110.186 \ No newline at end of file
   111.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   111.2 +++ b/launcher/fx/src/test/java/org/apidesign/bck2brwsr/launcher/fximpl/JsMethods.java	Mon Oct 07 14:20:58 2013 +0200
   111.3 @@ -0,0 +1,45 @@
   111.4 +/**
   111.5 + * Back 2 Browser Bytecode Translator
   111.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   111.7 + *
   111.8 + * This program is free software: you can redistribute it and/or modify
   111.9 + * it under the terms of the GNU General Public License as published by
  111.10 + * the Free Software Foundation, version 2 of the License.
  111.11 + *
  111.12 + * This program is distributed in the hope that it will be useful,
  111.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  111.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  111.15 + * GNU General Public License for more details.
  111.16 + *
  111.17 + * You should have received a copy of the GNU General Public License
  111.18 + * along with this program. Look for COPYING file in the top folder.
  111.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  111.20 + */
  111.21 +package org.apidesign.bck2brwsr.launcher.fximpl;
  111.22 +
  111.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  111.24 +
  111.25 +/**
  111.26 + *
  111.27 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  111.28 + */
  111.29 +public class JsMethods {
  111.30 +    @JavaScriptBody(args = {}, body = "return 42;")
  111.31 +    public static Object fortyTwo() {
  111.32 +        return -42;
  111.33 +    }
  111.34 +    
  111.35 +    @JavaScriptBody(args = {"x", "y" }, body = "return x + y;")
  111.36 +    public static native int plus(int x, int y);
  111.37 +    
  111.38 +    @JavaScriptBody(args = {"x"}, body = "return x;")
  111.39 +    public static native int plus(int x);
  111.40 +    
  111.41 +    @JavaScriptBody(args = {}, body = "return this;")
  111.42 +    public static native Object staticThis();
  111.43 +    
  111.44 +    @JavaScriptBody(args = {}, body = "return this;")
  111.45 +    public native Object getThis();
  111.46 +    @JavaScriptBody(args = {"x"}, body = "return x;")
  111.47 +    public native int plusInst(int x);
  111.48 +}
   112.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   112.2 +++ b/launcher/http/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   112.3 @@ -0,0 +1,60 @@
   112.4 +<?xml version="1.0"?>
   112.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   112.6 +  <modelVersion>4.0.0</modelVersion>
   112.7 +  <parent>
   112.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
   112.9 +    <artifactId>launcher-pom</artifactId>
  112.10 +    <version>0.9-SNAPSHOT</version>
  112.11 +  </parent>
  112.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
  112.13 +  <artifactId>launcher.http</artifactId>
  112.14 +  <version>0.9-SNAPSHOT</version>
  112.15 +  <name>Bck2Brwsr Launcher</name>
  112.16 +  <url>http://maven.apache.org</url>
  112.17 +    <build>
  112.18 +        <plugins>
  112.19 +            <plugin>
  112.20 +                <groupId>org.apache.maven.plugins</groupId>
  112.21 +                <artifactId>maven-compiler-plugin</artifactId>
  112.22 +                <version>2.3.2</version>
  112.23 +                <configuration>
  112.24 +                    <source>1.7</source>
  112.25 +                    <target>1.7</target>
  112.26 +                </configuration>
  112.27 +            </plugin>
  112.28 +            <plugin>
  112.29 +                <groupId>org.apache.maven.plugins</groupId>
  112.30 +                <artifactId>maven-javadoc-plugin</artifactId>
  112.31 +                <configuration>
  112.32 +                    <subpackages>org.apidesign.bck2brwsr.launcher.b2b</subpackages>
  112.33 +                    <skip>false</skip>
  112.34 +                </configuration>
  112.35 +            </plugin>
  112.36 +        </plugins>
  112.37 +    </build>
  112.38 +    <properties>
  112.39 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  112.40 +  </properties>
  112.41 +  <dependencies>
  112.42 +    <dependency>
  112.43 +      <groupId>${project.groupId}</groupId>
  112.44 +      <artifactId>launcher</artifactId>
  112.45 +      <version>${project.version}</version>
  112.46 +    </dependency>
  112.47 +    <dependency>
  112.48 +      <groupId>${project.groupId}</groupId>
  112.49 +      <artifactId>launcher.fx</artifactId>
  112.50 +      <version>${project.version}</version>
  112.51 +    </dependency>
  112.52 +    <dependency>
  112.53 +      <groupId>org.glassfish.grizzly</groupId>
  112.54 +      <artifactId>grizzly-http-server</artifactId>
  112.55 +      <version>${grizzly.version}</version>
  112.56 +    </dependency>
  112.57 +    <dependency>
  112.58 +      <groupId>${project.groupId}</groupId>
  112.59 +      <artifactId>vm4brwsr</artifactId>
  112.60 +      <version>${project.version}</version>
  112.61 +    </dependency>
  112.62 +  </dependencies>
  112.63 +</project>
   113.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   113.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Mon Oct 07 14:20:58 2013 +0200
   113.3 @@ -0,0 +1,70 @@
   113.4 +/**
   113.5 + * Back 2 Browser Bytecode Translator
   113.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   113.7 + *
   113.8 + * This program is free software: you can redistribute it and/or modify
   113.9 + * it under the terms of the GNU General Public License as published by
  113.10 + * the Free Software Foundation, version 2 of the License.
  113.11 + *
  113.12 + * This program is distributed in the hope that it will be useful,
  113.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  113.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  113.15 + * GNU General Public License for more details.
  113.16 + *
  113.17 + * You should have received a copy of the GNU General Public License
  113.18 + * along with this program. Look for COPYING file in the top folder.
  113.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  113.20 + */
  113.21 +package org.apidesign.bck2brwsr.launcher;
  113.22 +
  113.23 +import java.io.IOException;
  113.24 +import java.io.InputStream;
  113.25 +import org.apidesign.vm4brwsr.Bck2Brwsr;
  113.26 +
  113.27 +/**
  113.28 + * Lightweight server to launch Bck2Brwsr applications and tests.
  113.29 + * Supports execution in native browser as well as Java's internal 
  113.30 + * execution engine.
  113.31 + */
  113.32 +final class Bck2BrwsrLauncher extends BaseHTTPLauncher {
  113.33 +    
  113.34 +    public Bck2BrwsrLauncher(String cmd) {
  113.35 +        super(cmd);
  113.36 +    }
  113.37 +    
  113.38 +    @Override
  113.39 +    String harnessResource() {
  113.40 +        return "org/apidesign/bck2brwsr/launcher/harness.xhtml";
  113.41 +    }
  113.42 +    
  113.43 +    @Override
  113.44 +    void generateBck2BrwsrJS(StringBuilder sb, final Res loader) throws IOException {
  113.45 +        class R implements Bck2Brwsr.Resources {
  113.46 +            @Override
  113.47 +            public InputStream get(String resource) throws IOException {
  113.48 +                return loader.get(resource);
  113.49 +            }
  113.50 +        }
  113.51 +
  113.52 +        Bck2Brwsr.generate(sb, new R());
  113.53 +        sb.append(
  113.54 +              "(function WrapperVM(global) {"
  113.55 +            + "  function ldCls(res) {\n"
  113.56 +            + "    var request = new XMLHttpRequest();\n"
  113.57 +            + "    request.open('GET', '/classes/' + res, false);\n"
  113.58 +            + "    request.send();\n"
  113.59 +            + "    if (request.status !== 200) return null;\n"
  113.60 +            + "    var arr = eval('(' + request.responseText + ')');\n"
  113.61 +            + "    return arr;\n"
  113.62 +            + "  }\n"
  113.63 +            + "  var prevvm = global.bck2brwsr;\n"
  113.64 +            + "  global.bck2brwsr = function() {\n"
  113.65 +            + "    var args = Array.prototype.slice.apply(arguments);\n"
  113.66 +            + "    args.unshift(ldCls);\n"
  113.67 +            + "    return prevvm.apply(null, args);\n"
  113.68 +            + "  };\n"
  113.69 +            + "})(this);\n"
  113.70 +        );
  113.71 +    }
  113.72 +
  113.73 +}
   114.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   114.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Mon Oct 07 14:20:58 2013 +0200
   114.3 @@ -0,0 +1,135 @@
   114.4 +/**
   114.5 + * Back 2 Browser Bytecode Translator
   114.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   114.7 + *
   114.8 + * This program is free software: you can redistribute it and/or modify
   114.9 + * it under the terms of the GNU General Public License as published by
  114.10 + * the Free Software Foundation, version 2 of the License.
  114.11 + *
  114.12 + * This program is distributed in the hope that it will be useful,
  114.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  114.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  114.15 + * GNU General Public License for more details.
  114.16 + *
  114.17 + * You should have received a copy of the GNU General Public License
  114.18 + * along with this program. Look for COPYING file in the top folder.
  114.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  114.20 + */
  114.21 +package org.apidesign.bck2brwsr.launcher;
  114.22 +
  114.23 +import org.apidesign.bck2brwsr.launcher.impl.Console;
  114.24 +import java.io.IOException;
  114.25 +import java.io.InputStream;
  114.26 +import java.net.URL;
  114.27 +import java.util.Enumeration;
  114.28 +import java.util.LinkedHashSet;
  114.29 +import java.util.Set;
  114.30 +import java.util.logging.Level;
  114.31 +import java.util.logging.Logger;
  114.32 +import javax.script.Invocable;
  114.33 +import javax.script.ScriptEngine;
  114.34 +import javax.script.ScriptEngineManager;
  114.35 +import javax.script.ScriptException;
  114.36 +import org.apidesign.vm4brwsr.Bck2Brwsr;
  114.37 +
  114.38 +/**
  114.39 + * Tests execution in Java's internal scripting engine.
  114.40 + */
  114.41 +final class JSLauncher extends Launcher {
  114.42 +    private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
  114.43 +    private Set<ClassLoader> loaders = new LinkedHashSet<>();
  114.44 +    private final Res resources = new Res();
  114.45 +    private Invocable code;
  114.46 +    private StringBuilder codeSeq;
  114.47 +    private Object console;
  114.48 +
  114.49 +    JSLauncher() {
  114.50 +        addClassLoader(Bck2Brwsr.class.getClassLoader());
  114.51 +    }
  114.52 +    
  114.53 +    @Override InvocationContext runMethod(InvocationContext mi) {
  114.54 +        loaders.add(mi.clazz.getClassLoader());
  114.55 +        try {
  114.56 +            long time = System.currentTimeMillis();
  114.57 +            LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
  114.58 +            String res = code.invokeMethod(
  114.59 +                console,
  114.60 +                "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
  114.61 +                mi.clazz.getName(), mi.methodName).toString();
  114.62 +            time = System.currentTimeMillis() - time;
  114.63 +            LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
  114.64 +            mi.result(res, null);
  114.65 +        } catch (ScriptException | NoSuchMethodException ex) {
  114.66 +            mi.result(null, ex);
  114.67 +        }
  114.68 +        return mi;
  114.69 +    }
  114.70 +    
  114.71 +    public void addClassLoader(ClassLoader url) {
  114.72 +        this.loaders.add(url);
  114.73 +    }
  114.74 +
  114.75 +    @Override
  114.76 +    public void initialize() throws IOException {
  114.77 +        try {
  114.78 +            initRhino();
  114.79 +        } catch (Exception ex) {
  114.80 +            if (ex instanceof IOException) {
  114.81 +                throw (IOException)ex;
  114.82 +            }
  114.83 +            if (ex instanceof RuntimeException) {
  114.84 +                throw (RuntimeException)ex;
  114.85 +            }
  114.86 +            throw new IOException(ex);
  114.87 +        }
  114.88 +    }
  114.89 +    
  114.90 +    private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
  114.91 +        StringBuilder sb = new StringBuilder();
  114.92 +        Bck2Brwsr.generate(sb, new Res());
  114.93 +
  114.94 +        ScriptEngineManager sem = new ScriptEngineManager();
  114.95 +        ScriptEngine mach = sem.getEngineByExtension("js");
  114.96 +
  114.97 +        sb.append(
  114.98 +              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
  114.99 +            + "\nfunction initVM() { return vm; };"
 114.100 +            + "\n");
 114.101 +
 114.102 +        Object res = mach.eval(sb.toString());
 114.103 +        if (!(mach instanceof Invocable)) {
 114.104 +            throw new IOException("It is invocable object: " + res);
 114.105 +        }
 114.106 +        code = (Invocable) mach;
 114.107 +        codeSeq = sb;
 114.108 +        
 114.109 +        Object vm = code.invokeFunction("initVM");
 114.110 +        console = code.invokeMethod(vm, "loadClass", Console.class.getName());
 114.111 +    }
 114.112 +
 114.113 +    @Override
 114.114 +    public void shutdown() throws IOException {
 114.115 +    }
 114.116 +
 114.117 +    @Override
 114.118 +    public String toString() {
 114.119 +        return codeSeq.toString();
 114.120 +    }
 114.121 +    
 114.122 +    private class Res implements Bck2Brwsr.Resources {
 114.123 +        @Override
 114.124 +        public InputStream get(String resource) throws IOException {
 114.125 +            for (ClassLoader l : loaders) {
 114.126 +                URL u = null;
 114.127 +                Enumeration<URL> en = l.getResources(resource);
 114.128 +                while (en.hasMoreElements()) {
 114.129 +                    u = en.nextElement();
 114.130 +                }
 114.131 +                if (u != null) {
 114.132 +                    return u.openStream();
 114.133 +                }
 114.134 +            }
 114.135 +            throw new IOException("Can't find " + resource);
 114.136 +        }
 114.137 +    }
 114.138 +}
   115.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   115.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/b2b/LauncherBck2Brwsr.java	Mon Oct 07 14:20:58 2013 +0200
   115.3 @@ -0,0 +1,33 @@
   115.4 +/**
   115.5 + * Back 2 Browser Bytecode Translator
   115.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   115.7 + *
   115.8 + * This program is free software: you can redistribute it and/or modify
   115.9 + * it under the terms of the GNU General Public License as published by
  115.10 + * the Free Software Foundation, version 2 of the License.
  115.11 + *
  115.12 + * This program is distributed in the hope that it will be useful,
  115.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  115.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  115.15 + * GNU General Public License for more details.
  115.16 + *
  115.17 + * You should have received a copy of the GNU General Public License
  115.18 + * along with this program. Look for COPYING file in the top folder.
  115.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  115.20 + */
  115.21 +package org.apidesign.bck2brwsr.launcher.b2b;
  115.22 +
  115.23 +import java.awt.Desktop;
  115.24 +import org.apidesign.bck2brwsr.launcher.Launcher;
  115.25 +
  115.26 +/** This is a launcher for the <a href="http://bck2brwsr.apidesign.org">Bck2Brwsr</a>
  115.27 + * project that is using {@link Desktop} (or {@link Process}) to display the 
  115.28 + * external browser in separate process. Use {@link Launcher} methods to access this
  115.29 + * functionality via public, supported methods.
  115.30 + *
  115.31 + * @author Jaroslav Tulach
  115.32 + */
  115.33 +public final class LauncherBck2Brwsr {
  115.34 +    private LauncherBck2Brwsr() {
  115.35 +    }
  115.36 +}
   116.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   116.2 +++ b/launcher/http/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Mon Oct 07 14:20:58 2013 +0200
   116.3 @@ -0,0 +1,356 @@
   116.4 +/**
   116.5 + * Back 2 Browser Bytecode Translator
   116.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   116.7 + *
   116.8 + * This program is free software: you can redistribute it and/or modify
   116.9 + * it under the terms of the GNU General Public License as published by
  116.10 + * the Free Software Foundation, version 2 of the License.
  116.11 + *
  116.12 + * This program is distributed in the hope that it will be useful,
  116.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  116.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  116.15 + * GNU General Public License for more details.
  116.16 + *
  116.17 + * You should have received a copy of the GNU General Public License
  116.18 + * along with this program. Look for COPYING file in the top folder.
  116.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  116.20 + */
  116.21 +package org.apidesign.bck2brwsr.launcher.impl;
  116.22 +
  116.23 +import java.io.IOException;
  116.24 +import java.io.InputStream;
  116.25 +import java.io.UnsupportedEncodingException;
  116.26 +import java.lang.reflect.InvocationTargetException;
  116.27 +import java.lang.reflect.Method;
  116.28 +import java.lang.reflect.Modifier;
  116.29 +import java.net.URL;
  116.30 +import java.util.Enumeration;
  116.31 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  116.32 +
  116.33 +/**
  116.34 + *
  116.35 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  116.36 + */
  116.37 +public class Console {
  116.38 +    private Console() {
  116.39 +    }
  116.40 +    static {
  116.41 +        turnAssetionStatusOn();
  116.42 +    }
  116.43 +    
  116.44 +    @JavaScriptBody(args = {"id", "attr"}, body = 
  116.45 +        "return window.document.getElementById(id)[attr].toString();")
  116.46 +    private static native Object getAttr(String id, String attr);
  116.47 +    @JavaScriptBody(args = {"elem", "attr"}, body = 
  116.48 +        "return elem[attr].toString();")
  116.49 +    private static native Object getAttr(Object elem, String attr);
  116.50 +
  116.51 +    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
  116.52 +        "window.document.getElementById(id)[attr] = value;")
  116.53 +    private static native void setAttr(String id, String attr, Object value);
  116.54 +    @JavaScriptBody(args = {"elem", "attr", "value"}, body = 
  116.55 +        "elem[attr] = value;")
  116.56 +    private static native void setAttr(Object id, String attr, Object value);
  116.57 +    
  116.58 +    @JavaScriptBody(args = {}, body = "return; window.close();")
  116.59 +    private static native void closeWindow();
  116.60 +
  116.61 +    private static Object textArea;
  116.62 +    private static Object statusArea;
  116.63 +    
  116.64 +    private static void log(String newText) {
  116.65 +        if (textArea == null) {
  116.66 +            return;
  116.67 +        }
  116.68 +        String attr = "value";
  116.69 +        setAttr(textArea, attr, getAttr(textArea, attr) + "\n" + newText);
  116.70 +        setAttr(textArea, "scrollTop", getAttr(textArea, "scrollHeight"));
  116.71 +    }
  116.72 +    
  116.73 +    private static void beginTest(Case c) {
  116.74 +        Object[] arr = new Object[2];
  116.75 +        beginTest(c.getClassName() + "." + c.getMethodName(), c, arr);
  116.76 +        textArea = arr[0];
  116.77 +        statusArea = arr[1];
  116.78 +    }
  116.79 +    
  116.80 +    private static void finishTest(Case c, Object res) {
  116.81 +        if ("null".equals(res)) {
  116.82 +            setAttr(statusArea, "innerHTML", "Success");
  116.83 +        } else {
  116.84 +            setAttr(statusArea, "innerHTML", "Result " + res);
  116.85 +        }
  116.86 +        statusArea = null;
  116.87 +        textArea = null;
  116.88 +    }
  116.89 +
  116.90 +    @JavaScriptBody(args = { "test", "c", "arr" }, body = 
  116.91 +          "var ul = window.document.getElementById('bck2brwsr.result');\n"
  116.92 +        + "var li = window.document.createElement('li');\n"
  116.93 +        + "var span = window.document.createElement('span');"
  116.94 +        + "span.innerHTML = test + ' - ';\n"
  116.95 +        + "var details = window.document.createElement('a');\n"
  116.96 +        + "details.innerHTML = 'Details';\n"
  116.97 +        + "details.href = '#';\n"
  116.98 +        + "var p = window.document.createElement('p');\n"
  116.99 +        + "var status = window.document.createElement('a');\n"
 116.100 +        + "status.innerHTML = 'running';"
 116.101 +        + "details.onclick = function() { li.appendChild(p); li.removeChild(details); status.innerHTML = 'Run Again'; status.href = '#'; };\n"
 116.102 +        + "status.onclick = function() { c.again__V_3Ljava_lang_Object_2(arr); }\n"
 116.103 +        + "var pre = window.document.createElement('textarea');\n"
 116.104 +        + "pre.cols = 100;"
 116.105 +        + "pre.rows = 10;"
 116.106 +        + "li.appendChild(span);\n"
 116.107 +        + "li.appendChild(status);\n"
 116.108 +        + "var span = window.document.createElement('span');"
 116.109 +        + "span.innerHTML = ' ';\n"
 116.110 +        + "li.appendChild(span);\n"
 116.111 +        + "li.appendChild(details);\n"
 116.112 +        + "p.appendChild(pre);\n"
 116.113 +        + "ul.appendChild(li);\n"
 116.114 +        + "arr[0] = pre;\n"
 116.115 +        + "arr[1] = status;\n"
 116.116 +    )
 116.117 +    private static native void beginTest(String test, Case c, Object[] arr);
 116.118 +    
 116.119 +    @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
 116.120 +        + "var request = new XMLHttpRequest();\n"
 116.121 +        + "request.open('GET', url, true);\n"
 116.122 +        + "request.setRequestHeader('Content-Type', 'text/plain; charset=utf-8');\n"
 116.123 +        + "request.onreadystatechange = function() {\n"
 116.124 +        + "  if (this.readyState!==4) return;\n"
 116.125 +        + "  arr[0] = this.responseText;\n"
 116.126 +        + "  callback.run__V();\n"
 116.127 +        + "};"
 116.128 +        + "request.send();"
 116.129 +    )
 116.130 +    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
 116.131 +    
 116.132 +    public static void harness(String url) throws IOException {
 116.133 +        log("Connecting to " + url);
 116.134 +        Request r = new Request(url);
 116.135 +    }
 116.136 +    
 116.137 +    private static class Request implements Runnable {
 116.138 +        private final String[] arr = { null };
 116.139 +        private final String url;
 116.140 +        private Case c;
 116.141 +        private int retries;
 116.142 +
 116.143 +        private Request(String url) throws IOException {
 116.144 +            this.url = url;
 116.145 +            loadText(url, this, arr);
 116.146 +        }
 116.147 +        private Request(String url, String u) throws IOException {
 116.148 +            this.url = url;
 116.149 +            loadText(u, this, arr);
 116.150 +        }
 116.151 +        
 116.152 +        @Override
 116.153 +        public void run() {
 116.154 +            try {
 116.155 +                if (c == null) {
 116.156 +                    String data = arr[0];
 116.157 +
 116.158 +                    if (data == null) {
 116.159 +                        log("Some error exiting");
 116.160 +                        closeWindow();
 116.161 +                        return;
 116.162 +                    }
 116.163 +
 116.164 +                    if (data.isEmpty()) {
 116.165 +                        log("No data, exiting");
 116.166 +                        closeWindow();
 116.167 +                        return;
 116.168 +                    }
 116.169 +
 116.170 +                    c = Case.parseData(data);
 116.171 +                    beginTest(c);
 116.172 +                    log("Got \"" + data + "\"");
 116.173 +                } else {
 116.174 +                    log("Processing \"" + arr[0] + "\" for " + retries + " time");
 116.175 +                }
 116.176 +                Object result = retries++ >= 10 ? "java.lang.InterruptedException:timeout" : c.runTest();
 116.177 +                finishTest(c, result);
 116.178 +                
 116.179 +                String u = url + "?request=" + c.getRequestId() + "&result=" + result;
 116.180 +                new Request(url, u);
 116.181 +            } catch (Exception ex) {
 116.182 +                if (ex instanceof InterruptedException) {
 116.183 +                    log("Re-scheduling in 100ms");
 116.184 +                    schedule(this, 100);
 116.185 +                    return;
 116.186 +                }
 116.187 +                log(ex.getClass().getName() + ":" + ex.getMessage());
 116.188 +            }
 116.189 +        }
 116.190 +    }
 116.191 +    
 116.192 +    private static String encodeURL(String r) throws UnsupportedEncodingException {
 116.193 +        final String SPECIAL = "%$&+,/:;=?@";
 116.194 +        StringBuilder sb = new StringBuilder();
 116.195 +        byte[] utf8 = r.getBytes("UTF-8");
 116.196 +        for (int i = 0; i < utf8.length; i++) {
 116.197 +            int ch = utf8[i] & 0xff;
 116.198 +            if (ch < 32 || ch > 127 || SPECIAL.indexOf(ch) >= 0) {
 116.199 +                final String numbers = "0" + Integer.toHexString(ch);
 116.200 +                sb.append("%").append(numbers.substring(numbers.length() - 2));
 116.201 +            } else {
 116.202 +                if (ch == 32) {
 116.203 +                    sb.append("+");
 116.204 +                } else {
 116.205 +                    sb.append((char)ch);
 116.206 +                }
 116.207 +            }
 116.208 +        }
 116.209 +        return sb.toString();
 116.210 +    }
 116.211 +    
 116.212 +    static String invoke(String clazz, String method) throws 
 116.213 +    ClassNotFoundException, InvocationTargetException, IllegalAccessException, 
 116.214 +    InstantiationException, InterruptedException {
 116.215 +        final Object r = new Case(null).invokeMethod(clazz, method);
 116.216 +        return r == null ? "null" : r.toString().toString();
 116.217 +    }
 116.218 +
 116.219 +    /** Helper method that inspects the classpath and loads given resource
 116.220 +     * (usually a class file). Used while running tests in Rhino.
 116.221 +     * 
 116.222 +     * @param name resource name to find
 116.223 +     * @return the array of bytes in the given resource
 116.224 +     * @throws IOException I/O in case something goes wrong
 116.225 +     */
 116.226 +    public static byte[] read(String name) throws IOException {
 116.227 +        URL u = null;
 116.228 +        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
 116.229 +        while (en.hasMoreElements()) {
 116.230 +            u = en.nextElement();
 116.231 +        }
 116.232 +        if (u == null) {
 116.233 +            throw new IOException("Can't find " + name);
 116.234 +        }
 116.235 +        try (InputStream is = u.openStream()) {
 116.236 +            byte[] arr;
 116.237 +            arr = new byte[is.available()];
 116.238 +            int offset = 0;
 116.239 +            while (offset < arr.length) {
 116.240 +                int len = is.read(arr, offset, arr.length - offset);
 116.241 +                if (len == -1) {
 116.242 +                    throw new IOException("Can't read " + name);
 116.243 +                }
 116.244 +                offset += len;
 116.245 +            }
 116.246 +            return arr;
 116.247 +        }
 116.248 +    }
 116.249 +   
 116.250 +    @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
 116.251 +    private static void turnAssetionStatusOn() {
 116.252 +    }
 116.253 +
 116.254 +    @JavaScriptBody(args = {"r", "time"}, body =
 116.255 +        "return window.setTimeout(function() { r.run__V(); }, time);")
 116.256 +    private static native Object schedule(Runnable r, int time);
 116.257 +    
 116.258 +    private static final class Case {
 116.259 +        private final Object data;
 116.260 +        private Object inst;
 116.261 +
 116.262 +        private Case(Object data) {
 116.263 +            this.data = data;
 116.264 +        }
 116.265 +        
 116.266 +        public static Case parseData(String s) {
 116.267 +            return new Case(toJSON(s));
 116.268 +        }
 116.269 +        
 116.270 +        public String getMethodName() {
 116.271 +            return value("methodName", data);
 116.272 +        }
 116.273 +
 116.274 +        public String getClassName() {
 116.275 +            return value("className", data);
 116.276 +        }
 116.277 +        
 116.278 +        public String getRequestId() {
 116.279 +            return value("request", data);
 116.280 +        }
 116.281 +
 116.282 +        public String getHtmlFragment() {
 116.283 +            return value("html", data);
 116.284 +        }
 116.285 +        
 116.286 +        void again(Object[] arr) {
 116.287 +            try {
 116.288 +                textArea = arr[0];
 116.289 +                statusArea = arr[1];
 116.290 +                setAttr(textArea, "value", "");
 116.291 +                runTest();
 116.292 +            } catch (Exception ex) {
 116.293 +                log(ex.getClass().getName() + ":" + ex.getMessage());
 116.294 +            }
 116.295 +        }
 116.296 +
 116.297 +        private Object runTest() throws IllegalAccessException, 
 116.298 +        IllegalArgumentException, ClassNotFoundException, UnsupportedEncodingException, 
 116.299 +        InvocationTargetException, InstantiationException, InterruptedException {
 116.300 +            if (this.getHtmlFragment() != null) {
 116.301 +                setAttr("bck2brwsr.fragment", "innerHTML", this.getHtmlFragment());
 116.302 +            }
 116.303 +            log("Invoking " + this.getClassName() + '.' + this.getMethodName() + " as request: " + this.getRequestId());
 116.304 +            Object result = invokeMethod(this.getClassName(), this.getMethodName());
 116.305 +            setAttr("bck2brwsr.fragment", "innerHTML", "");
 116.306 +            log("Result: " + result);
 116.307 +            result = encodeURL("" + result);
 116.308 +            log("Sending back: ...?request=" + this.getRequestId() + "&result=" + result);
 116.309 +            return result;
 116.310 +        }
 116.311 +
 116.312 +        private Object invokeMethod(String clazz, String method)
 116.313 +        throws ClassNotFoundException, InvocationTargetException,
 116.314 +        InterruptedException, IllegalAccessException, IllegalArgumentException,
 116.315 +        InstantiationException {
 116.316 +            Method found = null;
 116.317 +            Class<?> c = Class.forName(clazz);
 116.318 +            for (Method m : c.getMethods()) {
 116.319 +                if (m.getName().equals(method)) {
 116.320 +                    found = m;
 116.321 +                }
 116.322 +            }
 116.323 +            Object res;
 116.324 +            if (found != null) {
 116.325 +                try {
 116.326 +                    if ((found.getModifiers() & Modifier.STATIC) != 0) {
 116.327 +                        res = found.invoke(null);
 116.328 +                    } else {
 116.329 +                        if (inst == null) {
 116.330 +                            inst = c.newInstance();
 116.331 +                        }
 116.332 +                        res = found.invoke(inst);
 116.333 +                    }
 116.334 +                } catch (Throwable ex) {
 116.335 +                    if (ex instanceof InvocationTargetException) {
 116.336 +                        ex = ((InvocationTargetException) ex).getTargetException();
 116.337 +                    }
 116.338 +                    if (ex instanceof InterruptedException) {
 116.339 +                        throw (InterruptedException)ex;
 116.340 +                    }
 116.341 +                    res = ex.getClass().getName() + ":" + ex.getMessage();
 116.342 +                }
 116.343 +            } else {
 116.344 +                res = "Can't find method " + method + " in " + clazz;
 116.345 +            }
 116.346 +            return res;
 116.347 +        }
 116.348 +        
 116.349 +        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
 116.350 +        private static native Object toJSON(String s);
 116.351 +        
 116.352 +        @JavaScriptBody(args = {"p", "d"}, body = 
 116.353 +              "var v = d[p];\n"
 116.354 +            + "if (typeof v === 'undefined') return null;\n"
 116.355 +            + "return v.toString();"
 116.356 +        )
 116.357 +        private static native String value(String p, Object d);
 116.358 +    }
 116.359 +}
   117.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   117.2 +++ b/launcher/http/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Mon Oct 07 14:20:58 2013 +0200
   117.3 @@ -0,0 +1,43 @@
   117.4 +<?xml version="1.0" encoding="UTF-8"?>
   117.5 +<!--
   117.6 +
   117.7 +    Back 2 Browser Bytecode Translator
   117.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   117.9 +
  117.10 +    This program is free software: you can redistribute it and/or modify
  117.11 +    it under the terms of the GNU General Public License as published by
  117.12 +    the Free Software Foundation, version 2 of the License.
  117.13 +
  117.14 +    This program is distributed in the hope that it will be useful,
  117.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
  117.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  117.17 +    GNU General Public License for more details.
  117.18 +
  117.19 +    You should have received a copy of the GNU General Public License
  117.20 +    along with this program. Look for COPYING file in the top folder.
  117.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
  117.22 +
  117.23 +-->
  117.24 +<!DOCTYPE html>
  117.25 +<html xmlns="http://www.w3.org/1999/xhtml">
  117.26 +    <head>
  117.27 +        <title>Bck2Brwsr Harness</title>
  117.28 +    </head>
  117.29 +    <body>
  117.30 +        <script src="/bck2brwsr.js"></script>
  117.31 +        <script>
  117.32 +            var vm = bck2brwsr();
  117.33 +        </script>
  117.34 +        
  117.35 +        <h1>Bck2Brwsr Execution Harness</h1>
  117.36 +        
  117.37 +        <ul id="bck2brwsr.result" style="width: 100%;" >
  117.38 +        </ul>
  117.39 +
  117.40 +        <div id="bck2brwsr.fragment"/>
  117.41 +        
  117.42 +        <script type="text/javascript">
  117.43 +            vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
  117.44 +        </script>
  117.45 +    </body>
  117.46 +</html>
   118.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   118.2 +++ b/launcher/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   118.3 @@ -0,0 +1,22 @@
   118.4 +<?xml version="1.0" encoding="UTF-8"?>
   118.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   118.6 +  <modelVersion>4.0.0</modelVersion>
   118.7 +  <parent>
   118.8 +    <artifactId>bck2brwsr</artifactId>
   118.9 +    <groupId>org.apidesign</groupId>
  118.10 +    <version>0.9-SNAPSHOT</version>
  118.11 +  </parent>
  118.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
  118.13 +  <artifactId>launcher-pom</artifactId>
  118.14 +  <version>0.9-SNAPSHOT</version>
  118.15 +  <packaging>pom</packaging>
  118.16 +  <name>Launchers</name>
  118.17 +  <properties>
  118.18 +      <grizzly.version>2.3.3</grizzly.version>
  118.19 +  </properties>
  118.20 +  <modules>
  118.21 +    <module>api</module>
  118.22 +    <module>http</module>
  118.23 +    <module>fx</module>
  118.24 +  </modules>
  118.25 +</project>
  118.26 \ No newline at end of file
   119.1 --- a/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   119.2 +++ b/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   119.3 @@ -3,7 +3,7 @@
   119.4    <modelVersion>4.0.0</modelVersion>
   119.5    <groupId>org.apidesign</groupId>
   119.6    <artifactId>bck2brwsr</artifactId>
   119.7 -  <version>0.3-SNAPSHOT</version>
   119.8 +  <version>0.9-SNAPSHOT</version>
   119.9    <packaging>pom</packaging>
  119.10    <name>Back 2 Browser</name>
  119.11    <parent>
  119.12 @@ -11,11 +11,19 @@
  119.13      <artifactId>jvnet-parent</artifactId>
  119.14      <version>3</version>
  119.15    </parent>  
  119.16 +  <properties>
  119.17 +      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  119.18 +      <netbeans.version>RELEASE73</netbeans.version>
  119.19 +      <license>COPYING</license>
  119.20 +      <net.java.html.version>0.6</net.java.html.version>
  119.21 +  </properties>
  119.22    <modules>
  119.23      <module>dew</module>
  119.24      <module>javaquery</module>
  119.25      <module>benchmarks</module>
  119.26      <module>ide</module>
  119.27 +    <module>ko</module>
  119.28 +    <module>launcher</module>
  119.29      <module>rt</module>
  119.30    </modules>
  119.31    <licenses>
  119.32 @@ -33,6 +41,7 @@
  119.33        <connection>scm:hg:http://source.apidesign.org/hg/bck2brwsr</connection>
  119.34        <developerConnection>scm:hg:https://source.apidesign.org/hg/bck2brwsr</developerConnection>
  119.35        <url>http://source.apidesign.org/hg/bck2brwsr</url>
  119.36 +    <tag>HEAD</tag>
  119.37    </scm>
  119.38    <repositories>
  119.39        <repository>
  119.40 @@ -78,14 +87,26 @@
  119.41                         <exclude>*</exclude>
  119.42                         <exclude>.*/**</exclude>
  119.43                         <exclude>rt/emul/*/src/main/**</exclude>
  119.44 -                       <exclude>rt/javap/**</exclude>
  119.45 -                       <exclude>rt/mojo/src/main/resources/archetype-resources/**</exclude>
  119.46 -                       <exclude>rt/vmtest/src/test/resources/**</exclude>
  119.47 +                       <exclude>rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java</exclude>
  119.48 +                       <exclude>rt/archetype/src/main/resources/archetype-resources/**</exclude>
  119.49 +                       <exclude>rt/emul/compact/src/test/resources/**</exclude>
  119.50                         <exclude>dew/src/main/resources/org/apidesign/bck2brwsr/dew/**</exclude>
  119.51                         <exclude>javaquery/api/src/main/resources/org/apidesign/bck2brwsr/htmlpage/knockout*.js</exclude>
  119.52 +                       <exclude>ko/archetype/src/main/resources/archetype-resources/**</exclude>
  119.53 +                       <exclude>ko/*/src/main/resources/org/apidesign/*/*/knockout-2.2.1.js</exclude>
  119.54                    </excludes>
  119.55                </configuration>
  119.56            </plugin>
  119.57 +           <plugin>
  119.58 +            <artifactId>maven-release-plugin</artifactId>
  119.59 +            <version>2.4</version>
  119.60 +            <configuration>
  119.61 +              <mavenExecutorId>forked-path</mavenExecutorId>
  119.62 +              <useReleaseProfile>false</useReleaseProfile>
  119.63 +              <arguments>-Pjvnet-release -Pgpg</arguments>
  119.64 +              <tag>release-${releaseVersion}</tag>
  119.65 +            </configuration>
  119.66 +          </plugin>
  119.67        </plugins>
  119.68        <pluginManagement>
  119.69            <plugins>
  119.70 @@ -94,6 +115,23 @@
  119.71                  <artifactId>maven-surefire-plugin</artifactId>
  119.72                  <version>2.13</version>
  119.73                </plugin>
  119.74 +              <plugin>
  119.75 +                <groupId>org.apache.maven.plugins</groupId>
  119.76 +                <artifactId>maven-javadoc-plugin</artifactId>
  119.77 +                <version>2.9</version>
  119.78 +                <configuration>
  119.79 +                    <skip>true</skip>
  119.80 +                </configuration>
  119.81 +              </plugin>
  119.82 +            <plugin>
  119.83 +                <groupId>org.apache.maven.plugins</groupId>
  119.84 +                <artifactId>maven-compiler-plugin</artifactId>
  119.85 +                <version>2.3.2</version>
  119.86 +                <configuration>
  119.87 +                    <source>1.7</source>
  119.88 +                    <target>1.7</target>
  119.89 +                </configuration>
  119.90 +            </plugin>
  119.91            </plugins>
  119.92        </pluginManagement>
  119.93    </build>
  119.94 @@ -114,19 +152,137 @@
  119.95          <dependency>
  119.96            <groupId>org.netbeans.api</groupId>
  119.97            <artifactId>org-netbeans-modules-classfile</artifactId>
  119.98 -          <version>RELEASE72</version>
  119.99 +          <version>${netbeans.version}</version>
 119.100            <type>jar</type>
 119.101          </dependency>
 119.102          <dependency>
 119.103            <groupId>org.netbeans.api</groupId>
 119.104            <artifactId>org-openide-util-lookup</artifactId>
 119.105 -          <version>RELEASE72</version>
 119.106 +          <version>${netbeans.version}</version>
 119.107            <scope>compile</scope>
 119.108            <type>jar</type>
 119.109          </dependency>
 119.110 +        <dependency>
 119.111 +            <groupId>org.netbeans.api</groupId>
 119.112 +            <artifactId>org-netbeans-api-annotations-common</artifactId>
 119.113 +            <version>${netbeans.version}</version>
 119.114 +        </dependency>
 119.115 +        <dependency>
 119.116 +            <groupId>org.netbeans.api</groupId>
 119.117 +            <artifactId>org-netbeans-modules-java-source</artifactId>
 119.118 +            <version>${netbeans.version}</version>
 119.119 +        </dependency>
 119.120 +        <dependency>
 119.121 +            <groupId>org.netbeans.api</groupId>
 119.122 +            <artifactId>org-netbeans-libs-javacapi</artifactId>
 119.123 +            <version>${netbeans.version}</version>
 119.124 +        </dependency>
 119.125 +        <dependency>
 119.126 +            <groupId>org.netbeans.api</groupId>
 119.127 +            <artifactId>org-netbeans-spi-java-hints</artifactId>
 119.128 +            <version>${netbeans.version}</version>
 119.129 +        </dependency>
 119.130 +        <dependency>
 119.131 +            <groupId>org.netbeans.api</groupId>
 119.132 +            <artifactId>org-netbeans-modules-parsing-api</artifactId>
 119.133 +            <version>${netbeans.version}</version>
 119.134 +        </dependency>
 119.135 +        <dependency>
 119.136 +            <groupId>org.netbeans.api</groupId>
 119.137 +            <artifactId>org-netbeans-spi-editor-hints</artifactId>
 119.138 +            <version>${netbeans.version}</version>
 119.139 +        </dependency>
 119.140 +        <dependency>
 119.141 +            <groupId>org.netbeans.api</groupId>
 119.142 +            <artifactId>org-openide-util</artifactId>
 119.143 +            <version>${netbeans.version}</version>
 119.144 +        </dependency>
 119.145 +        <dependency>
 119.146 +            <groupId>org.netbeans.api</groupId>
 119.147 +            <artifactId>org-netbeans-modules-java-lexer</artifactId>
 119.148 +            <version>${netbeans.version}</version>
 119.149 +        </dependency>
 119.150 +        <dependency>
 119.151 +            <groupId>org.netbeans.api</groupId>
 119.152 +            <artifactId>org-netbeans-modules-lexer</artifactId>
 119.153 +            <version>${netbeans.version}</version>
 119.154 +        </dependency>
 119.155 +        <dependency>
 119.156 +            <groupId>org.netbeans.api</groupId>
 119.157 +            <artifactId>org-netbeans-modules-java-hints-test</artifactId>
 119.158 +            <version>${netbeans.version}</version>
 119.159 +        </dependency>
 119.160 +        <dependency>
 119.161 +            <groupId>org.netbeans.api</groupId>
 119.162 +            <artifactId>org-netbeans-libs-junit4</artifactId>
 119.163 +            <version>${netbeans.version}</version>
 119.164 +        </dependency>
 119.165 +        <dependency>
 119.166 +            <groupId>org.netbeans.modules</groupId>
 119.167 +            <artifactId>org-netbeans-lib-nbjavac</artifactId>
 119.168 +            <version>${netbeans.version}</version>
 119.169 +        </dependency>
 119.170 +        <dependency> 
 119.171 +            <groupId>org.netbeans.modules</groupId>
 119.172 +            <artifactId>org-netbeans-modules-web-browser-api</artifactId>
 119.173 +            <version>${netbeans.version}</version>
 119.174 +            <exclusions>
 119.175 +                <exclusion>
 119.176 +                    <artifactId>org-netbeans-core</artifactId>
 119.177 +                    <groupId>org.netbeans.modules</groupId>
 119.178 +                </exclusion>
 119.179 +                <exclusion>
 119.180 +                    <artifactId>org-netbeans-core-multiview</artifactId>
 119.181 +                    <groupId>org.netbeans.api</groupId>
 119.182 +                </exclusion>
 119.183 +                <exclusion>
 119.184 +                    <artifactId>org-netbeans-libs-lucene</artifactId>
 119.185 +                    <groupId>org.netbeans.api</groupId>
 119.186 +                </exclusion>
 119.187 +                <exclusion>
 119.188 +                    <artifactId>org-netbeans-modules-diff</artifactId>
 119.189 +                    <groupId>org.netbeans.api</groupId>
 119.190 +                </exclusion>
 119.191 +                <exclusion>
 119.192 +                    <artifactId>org-netbeans-modules-editor-fold</artifactId>
 119.193 +                    <groupId>org.netbeans.api</groupId>
 119.194 +                </exclusion>
 119.195 +                <exclusion>
 119.196 +                    <artifactId>org-netbeans-modules-editor-guards</artifactId>
 119.197 +                    <groupId>org.netbeans.api</groupId>
 119.198 +                </exclusion>
 119.199 +            </exclusions>
 119.200 +        </dependency>
 119.201 +        <dependency>
 119.202 +            <artifactId>org-netbeans-modules-projectapi</artifactId>
 119.203 +            <groupId>org.netbeans.api</groupId>
 119.204 +            <type>jar</type>
 119.205 +            <version>${netbeans.version}</version>
 119.206 +        </dependency>
 119.207        </dependencies>
 119.208    </dependencyManagement>
 119.209 -  <properties>
 119.210 -      <license>COPYING</license>
 119.211 -  </properties>
 119.212 -</project>
 119.213 \ No newline at end of file
 119.214 +  <profiles>
 119.215 +      <profile>
 119.216 +          <id>jdk8</id>
 119.217 +          <activation>
 119.218 +              <file>
 119.219 +                  <exists>${java.home}/lib/ext/jfxrt.jar</exists>
 119.220 +              </file>
 119.221 +          </activation>
 119.222 +          <properties>
 119.223 +            <jfxrt.jar>${java.home}/lib/ext/jfxrt.jar</jfxrt.jar>
 119.224 +          </properties>
 119.225 +      </profile>
 119.226 +      <profile>
 119.227 +          <id>jdk7</id>
 119.228 +          <activation>
 119.229 +              <file>
 119.230 +                  <exists>${java.home}/lib/jfxrt.jar</exists>
 119.231 +              </file>
 119.232 +          </activation>
 119.233 +          <properties>
 119.234 +            <jfxrt.jar>${java.home}/lib/jfxrt.jar</jfxrt.jar>
 119.235 +          </properties>
 119.236 +      </profile>
 119.237 +  </profiles>
 119.238 +</project>
   120.1 --- a/rt/core/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   120.2 +++ b/rt/core/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   120.3 @@ -1,15 +1,14 @@
   120.4  <?xml version="1.0"?>
   120.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   120.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   120.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   120.8    <modelVersion>4.0.0</modelVersion>
   120.9    <parent>
  120.10      <groupId>org.apidesign.bck2brwsr</groupId>
  120.11      <artifactId>rt</artifactId>
  120.12 -    <version>0.3-SNAPSHOT</version>
  120.13 +    <version>0.9-SNAPSHOT</version>
  120.14    </parent>
  120.15    <groupId>org.apidesign.bck2brwsr</groupId>
  120.16    <artifactId>core</artifactId>
  120.17 -  <version>0.3-SNAPSHOT</version>
  120.18 +  <version>0.9-SNAPSHOT</version>
  120.19    <name>Bck2Brwsr Native Annotations</name>
  120.20    <url>http://maven.apache.org</url>
  120.21      <build>
  120.22 @@ -23,6 +22,14 @@
  120.23                      <target>1.7</target>
  120.24                  </configuration>
  120.25              </plugin>
  120.26 +            <plugin>
  120.27 +                <groupId>org.apache.maven.plugins</groupId>
  120.28 +                <artifactId>maven-javadoc-plugin</artifactId>
  120.29 +                <configuration>
  120.30 +                    <excludePackageNames>org.apidesign.bck2brwsr.core.impl</excludePackageNames>
  120.31 +                    <skip>false</skip>
  120.32 +                </configuration>
  120.33 +            </plugin>
  120.34          </plugins>
  120.35      </build>
  120.36      <properties>
   121.1 --- a/rt/core/src/main/java/org/apidesign/bck2brwsr/core/ExtraJavaScript.java	Wed Feb 27 17:50:47 2013 +0100
   121.2 +++ b/rt/core/src/main/java/org/apidesign/bck2brwsr/core/ExtraJavaScript.java	Mon Oct 07 14:20:58 2013 +0200
   121.3 @@ -22,14 +22,16 @@
   121.4  import java.lang.annotation.RetentionPolicy;
   121.5  import java.lang.annotation.Target;
   121.6  
   121.7 -/**
   121.8 +/** A way to include pre-made JavaScript scripts and libraries.
   121.9 + * The {@link #resource()} is loaded into the JavaScript VM and its object
  121.10 + * can be referenced from the class annotated by this annotation.
  121.11   *
  121.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
  121.13   */
  121.14  @Retention(RetentionPolicy.CLASS)
  121.15  @Target(ElementType.TYPE)
  121.16  public @interface ExtraJavaScript {
  121.17 -    /** location of a script to load */
  121.18 +    /** fully qualified location of a script to load. Start the path with slash. */
  121.19      String resource();
  121.20      /** should the class file still be processed or not? */
  121.21      boolean processByteCode() default true;
   122.1 --- a/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java	Wed Feb 27 17:50:47 2013 +0100
   122.2 +++ b/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptBody.java	Mon Oct 07 14:20:58 2013 +0200
   122.3 @@ -22,22 +22,17 @@
   122.4  import java.lang.annotation.RetentionPolicy;
   122.5  import java.lang.annotation.Target;
   122.6  
   122.7 -/** Put this method on a method in case it should have a special
   122.8 - * body in the <em>JavaScript</em>.
   122.9 +/** Put this annotation on a method to provide its special implementation
  122.10 + * in JavaScript. This is a way to define <em>native</em> methods that 
  122.11 + * interact with the surrounding environment.
  122.12   *
  122.13   * @author Jaroslav Tulach <jtulach@netbeans.org>
  122.14   */
  122.15  @Retention(RetentionPolicy.CLASS)
  122.16  @Target({ ElementType.METHOD, ElementType.CONSTRUCTOR })
  122.17  public @interface JavaScriptBody {
  122.18 -    /** Names of parameters for the method. 
  122.19 -     * 
  122.20 -     * <!--
  122.21 -     * If not specified
  122.22 -     * it will be <code>arg0, arg1, arg2</code>. In case of
  122.23 -     * instance methods, the <code>arg0</code> is reference
  122.24 -     * to <code>this</code>.
  122.25 -     * -->
  122.26 +    /** Names of parameters for the method generated method that can
  122.27 +     * be referenced from {@link #body()}.
  122.28       * 
  122.29       * @return array of the names of parameters for the method
  122.30       *    in JavaScript
  122.31 @@ -46,6 +41,12 @@
  122.32      
  122.33      /** The actual body of the method in JavaScript. This string will be
  122.34       * put into generated header (ends with '{') and footer (ends with '}').
  122.35 +     * The body can reference provided arguments. In case of non-static
  122.36 +     * instance method it may reference <code>this</code>. It can also 
  122.37 +     * call methods and access fields - if 
  122.38 +     * <a href="http://wiki.apidesign.org/wiki/Bck2BrwsrMangling">proper mangling</a> 
  122.39 +     * is used. Methods that return some value should end with <code>return</code> 
  122.40 +     * statement.
  122.41       */
  122.42      public String body();
  122.43  }
   123.1 --- a/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptOnly.java	Wed Feb 27 17:50:47 2013 +0100
   123.2 +++ b/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptOnly.java	Mon Oct 07 14:20:58 2013 +0200
   123.3 @@ -22,16 +22,17 @@
   123.4  import java.lang.annotation.RetentionPolicy;
   123.5  import java.lang.annotation.Target;
   123.6  
   123.7 -/** Don't include given field or method in generated JavaScript. Rather
   123.8 - * generate completely independent JavaScript code.
   123.9 +/** Don't include given method in the generated JavaScript at all. Rather
  123.10 + * generate completely independent JavaScript code consisting of
  123.11 + * <code>"{@link #name()}" = "{@link #value()}"</code>.
  123.12   *
  123.13   * @author Jaroslav Tulach <jtulach@netbeans.org>
  123.14   */
  123.15  @Retention(RetentionPolicy.CLASS)
  123.16 -@Target({ ElementType.METHOD, ElementType.FIELD })
  123.17 +@Target({ ElementType.METHOD })
  123.18  public @interface JavaScriptOnly {
  123.19      /** name of the variable to assign given value to */
  123.20      String name() default "";
  123.21 -    /** value to assign to given field */
  123.22 +    /** value to assign to the {@link #name()} variable */
  123.23      String value() default "";
  123.24  }
   124.1 --- a/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java	Wed Feb 27 17:50:47 2013 +0100
   124.2 +++ b/rt/core/src/main/java/org/apidesign/bck2brwsr/core/JavaScriptPrototype.java	Mon Oct 07 14:20:58 2013 +0200
   124.3 @@ -22,7 +22,14 @@
   124.4  import java.lang.annotation.RetentionPolicy;
   124.5  import java.lang.annotation.Target;
   124.6  
   124.7 -/** Controls how JavaScript inheritance should be handled.
   124.8 +/** Influence the inheritance of your class when converted to JavaScript.
   124.9 + * Sometimes one does not want
  124.10 + * to mimic the Java hierarchy, but modify it a bit. For example it makes
  124.11 + * sense to treat every (JavaScript) string literal as {@link String}.
  124.12 + * One can do it by making {@link String} subclass JavaScript <code>String</code>
  124.13 + * and use <code>String.prototype</code> as a container for all {@link String}
  124.14 + * methods.
  124.15 + * 
  124.16   * @author Jaroslav Tulach <jtulach@netbeans.org>
  124.17   */
  124.18  @Retention(RetentionPolicy.CLASS)
   125.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   125.2 +++ b/rt/emul/brwsrtest/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   125.3 @@ -0,0 +1,52 @@
   125.4 +<?xml version="1.0"?>
   125.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   125.6 +  <modelVersion>4.0.0</modelVersion>
   125.7 +  <parent>
   125.8 +    <groupId>org.apidesign.bck2brwsr</groupId>
   125.9 +    <artifactId>emul.pom</artifactId>
  125.10 +    <version>0.9-SNAPSHOT</version>
  125.11 +  </parent>
  125.12 +  <groupId>org.apidesign.bck2brwsr</groupId>
  125.13 +  <artifactId>brwsrtest</artifactId>
  125.14 +  <version>0.9-SNAPSHOT</version>
  125.15 +  <name>Tests Inside Real Browser</name>
  125.16 +  <url>http://maven.apache.org</url>
  125.17 +  <properties>
  125.18 +    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  125.19 +  </properties>
  125.20 +  <build>
  125.21 +      <plugins>
  125.22 +          <plugin>
  125.23 +           <groupId>org.apache.maven.plugins</groupId>
  125.24 +           <artifactId>maven-deploy-plugin</artifactId>
  125.25 +           <version>2.7</version>
  125.26 +           <configuration>
  125.27 +             <skip>true</skip>
  125.28 +           </configuration>
  125.29 +         </plugin>      
  125.30 +          <plugin>
  125.31 +              <groupId>org.apache.maven.plugins</groupId>
  125.32 +              <artifactId>maven-surefire-plugin</artifactId>
  125.33 +              <configuration>
  125.34 +                  <systemPropertyVariables>
  125.35 +                      <vmtest.js>brwsr</vmtest.js>
  125.36 +                  </systemPropertyVariables>
  125.37 +              </configuration>
  125.38 +          </plugin>
  125.39 +      </plugins>
  125.40 +  </build>
  125.41 +  <dependencies>
  125.42 +    <dependency>
  125.43 +      <groupId>${project.groupId}</groupId>
  125.44 +      <artifactId>vmtest</artifactId>
  125.45 +      <version>${project.version}</version>
  125.46 +      <scope>test</scope>
  125.47 +    </dependency>
  125.48 +    <dependency>
  125.49 +      <groupId>${project.groupId}</groupId>
  125.50 +      <artifactId>launcher.http</artifactId>
  125.51 +      <version>${project.version}</version>
  125.52 +      <scope>provided</scope>
  125.53 +    </dependency>
  125.54 +  </dependencies>
  125.55 +</project>
   126.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   126.2 +++ b/rt/emul/brwsrtest/src/test/java/org/apidesign/bck2brwsr/brwsrtest/BooleanTest.java	Mon Oct 07 14:20:58 2013 +0200
   126.3 @@ -0,0 +1,49 @@
   126.4 +/**
   126.5 + * Back 2 Browser Bytecode Translator
   126.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   126.7 + *
   126.8 + * This program is free software: you can redistribute it and/or modify
   126.9 + * it under the terms of the GNU General Public License as published by
  126.10 + * the Free Software Foundation, version 2 of the License.
  126.11 + *
  126.12 + * This program is distributed in the hope that it will be useful,
  126.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  126.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  126.15 + * GNU General Public License for more details.
  126.16 + *
  126.17 + * You should have received a copy of the GNU General Public License
  126.18 + * along with this program. Look for COPYING file in the top folder.
  126.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  126.20 + */
  126.21 +package org.apidesign.bck2brwsr.brwsrtest;
  126.22 +
  126.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  126.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  126.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
  126.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  126.27 +import org.testng.annotations.Factory;
  126.28 +
  126.29 +/**
  126.30 + *
  126.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  126.32 + */
  126.33 +public class BooleanTest {
  126.34 +    @JavaScriptBody(args = { "tr" }, body = "return tr ? true : false;")
  126.35 +    private static native Object trueFalse(boolean tr);
  126.36 +    
  126.37 +    @BrwsrTest public void isTrueInstanceOfBoolean() {
  126.38 +        Object t = trueFalse(true);
  126.39 +        assert t instanceof Boolean : "Should be boolean: " + t;
  126.40 +        assert ((boolean)t) : "and is true";
  126.41 +    }
  126.42 +    
  126.43 +    @BrwsrTest public void isFalseInstanceOfBoolean() {
  126.44 +        Object t = trueFalse(false);
  126.45 +        assert t instanceof Boolean : "Should be boolean: " + t;
  126.46 +        assert !((boolean)t) : "and is false: " + t;
  126.47 +    }
  126.48 +
  126.49 +    @Factory public static Object[] create() {
  126.50 +        return VMTest.create(BooleanTest.class);
  126.51 +    }
  126.52 +}
   127.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   127.2 +++ b/rt/emul/brwsrtest/src/test/java/org/apidesign/bck2brwsr/brwsrtest/DoubleBitsTest.java	Mon Oct 07 14:20:58 2013 +0200
   127.3 @@ -0,0 +1,42 @@
   127.4 +/**
   127.5 + * Back 2 Browser Bytecode Translator
   127.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   127.7 + *
   127.8 + * This program is free software: you can redistribute it and/or modify
   127.9 + * it under the terms of the GNU General Public License as published by
  127.10 + * the Free Software Foundation, version 2 of the License.
  127.11 + *
  127.12 + * This program is distributed in the hope that it will be useful,
  127.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  127.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  127.15 + * GNU General Public License for more details.
  127.16 + *
  127.17 + * You should have received a copy of the GNU General Public License
  127.18 + * along with this program. Look for COPYING file in the top folder.
  127.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  127.20 + */
  127.21 +package org.apidesign.bck2brwsr.brwsrtest;
  127.22 +
  127.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  127.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  127.25 +import org.testng.annotations.Factory;
  127.26 +
  127.27 +/**
  127.28 + *
  127.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  127.30 + */
  127.31 +public class DoubleBitsTest {
  127.32 +
  127.33 +    @Compare public String doubleToBits() {
  127.34 +        long val = Double.doubleToLongBits(333.456);
  127.35 +        return Long.toString(val);
  127.36 +    }
  127.37 +
  127.38 +    @Compare public int floatToBits() {
  127.39 +        return Float.floatToIntBits(333.456f);
  127.40 +    }
  127.41 +    
  127.42 +    @Factory public static Object[] create() {
  127.43 +        return VMTest.create(DoubleBitsTest.class);
  127.44 +    }
  127.45 +}
   128.1 --- a/rt/emul/compact/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   128.2 +++ b/rt/emul/compact/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   128.3 @@ -1,15 +1,14 @@
   128.4  <?xml version="1.0"?>
   128.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   128.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   128.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   128.8    <modelVersion>4.0.0</modelVersion>
   128.9    <parent>
  128.10      <groupId>org.apidesign.bck2brwsr</groupId>
  128.11      <artifactId>emul.pom</artifactId>
  128.12 -    <version>0.3-SNAPSHOT</version>
  128.13 +    <version>0.9-SNAPSHOT</version>
  128.14    </parent>
  128.15    <groupId>org.apidesign.bck2brwsr</groupId>
  128.16    <artifactId>emul</artifactId>
  128.17 -  <version>0.3-SNAPSHOT</version>
  128.18 +  <version>0.9-SNAPSHOT</version>
  128.19    <name>Bck2Brwsr API Profile</name>
  128.20    <url>http://maven.apache.org</url>
  128.21    <properties>
  128.22 @@ -29,6 +28,18 @@
  128.23        <scope>test</scope>
  128.24      </dependency>
  128.25      <dependency>
  128.26 +      <groupId>${project.groupId}</groupId>
  128.27 +      <artifactId>launcher.http</artifactId>
  128.28 +      <version>${project.version}</version>
  128.29 +      <scope>test</scope>
  128.30 +      <exclusions>
  128.31 +          <exclusion>
  128.32 +              <groupId>com.oracle</groupId>
  128.33 +              <artifactId>javafx</artifactId>
  128.34 +          </exclusion>
  128.35 +      </exclusions>
  128.36 +    </dependency>
  128.37 +    <dependency>
  128.38        <groupId>org.netbeans.api</groupId>
  128.39        <artifactId>org-openide-util-lookup</artifactId>
  128.40        <scope>test</scope>
  128.41 @@ -48,6 +59,15 @@
  128.42                   <target>1.7</target>
  128.43                </configuration>
  128.44            </plugin>
  128.45 +          <plugin>
  128.46 +              <groupId>org.apache.maven.plugins</groupId>
  128.47 +              <artifactId>maven-javadoc-plugin</artifactId>
  128.48 +              <configuration>
  128.49 +                  <excludePackageNames>org.apidesign.bck2brwsr.emul.*</excludePackageNames>
  128.50 +                  <skip>false</skip>
  128.51 +                  <includeDependencySources>true</includeDependencySources>
  128.52 +              </configuration>
  128.53 +          </plugin>
  128.54           <plugin>
  128.55              <artifactId>maven-assembly-plugin</artifactId>
  128.56                  <version>2.4</version>
   129.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   129.2 +++ b/rt/emul/compact/src/main/java/java/io/BufferedWriter.java	Mon Oct 07 14:20:58 2013 +0200
   129.3 @@ -0,0 +1,271 @@
   129.4 +/*
   129.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   129.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   129.7 + *
   129.8 + * This code is free software; you can redistribute it and/or modify it
   129.9 + * under the terms of the GNU General Public License version 2 only, as
  129.10 + * published by the Free Software Foundation.  Oracle designates this
  129.11 + * particular file as subject to the "Classpath" exception as provided
  129.12 + * by Oracle in the LICENSE file that accompanied this code.
  129.13 + *
  129.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  129.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  129.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  129.17 + * version 2 for more details (a copy is included in the LICENSE file that
  129.18 + * accompanied this code).
  129.19 + *
  129.20 + * You should have received a copy of the GNU General Public License version
  129.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  129.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  129.23 + *
  129.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  129.25 + * or visit www.oracle.com if you need additional information or have any
  129.26 + * questions.
  129.27 + */
  129.28 +
  129.29 +package java.io;
  129.30 +
  129.31 +
  129.32 +/**
  129.33 + * Writes text to a character-output stream, buffering characters so as to
  129.34 + * provide for the efficient writing of single characters, arrays, and strings.
  129.35 + *
  129.36 + * <p> The buffer size may be specified, or the default size may be accepted.
  129.37 + * The default is large enough for most purposes.
  129.38 + *
  129.39 + * <p> A newLine() method is provided, which uses the platform's own notion of
  129.40 + * line separator as defined by the system property <tt>line.separator</tt>.
  129.41 + * Not all platforms use the newline character ('\n') to terminate lines.
  129.42 + * Calling this method to terminate each output line is therefore preferred to
  129.43 + * writing a newline character directly.
  129.44 + *
  129.45 + * <p> In general, a Writer sends its output immediately to the underlying
  129.46 + * character or byte stream.  Unless prompt output is required, it is advisable
  129.47 + * to wrap a BufferedWriter around any Writer whose write() operations may be
  129.48 + * costly, such as FileWriters and OutputStreamWriters.  For example,
  129.49 + *
  129.50 + * <pre>
  129.51 + * PrintWriter out
  129.52 + *   = new PrintWriter(new BufferedWriter(new FileWriter("foo.out")));
  129.53 + * </pre>
  129.54 + *
  129.55 + * will buffer the PrintWriter's output to the file.  Without buffering, each
  129.56 + * invocation of a print() method would cause characters to be converted into
  129.57 + * bytes that would then be written immediately to the file, which can be very
  129.58 + * inefficient.
  129.59 + *
  129.60 + * @see PrintWriter
  129.61 + * @see FileWriter
  129.62 + * @see OutputStreamWriter
  129.63 + * @see java.nio.file.Files#newBufferedWriter
  129.64 + *
  129.65 + * @author      Mark Reinhold
  129.66 + * @since       JDK1.1
  129.67 + */
  129.68 +
  129.69 +public class BufferedWriter extends Writer {
  129.70 +
  129.71 +    private Writer out;
  129.72 +
  129.73 +    private char cb[];
  129.74 +    private int nChars, nextChar;
  129.75 +
  129.76 +    private static int defaultCharBufferSize = 8192;
  129.77 +
  129.78 +    /**
  129.79 +     * Line separator string.  This is the value of the line.separator
  129.80 +     * property at the moment that the stream was created.
  129.81 +     */
  129.82 +    private String lineSeparator;
  129.83 +
  129.84 +    /**
  129.85 +     * Creates a buffered character-output stream that uses a default-sized
  129.86 +     * output buffer.
  129.87 +     *
  129.88 +     * @param  out  A Writer
  129.89 +     */
  129.90 +    public BufferedWriter(Writer out) {
  129.91 +        this(out, defaultCharBufferSize);
  129.92 +    }
  129.93 +
  129.94 +    /**
  129.95 +     * Creates a new buffered character-output stream that uses an output
  129.96 +     * buffer of the given size.
  129.97 +     *
  129.98 +     * @param  out  A Writer
  129.99 +     * @param  sz   Output-buffer size, a positive integer
 129.100 +     *
 129.101 +     * @exception  IllegalArgumentException  If sz is <= 0
 129.102 +     */
 129.103 +    public BufferedWriter(Writer out, int sz) {
 129.104 +        super(out);
 129.105 +        if (sz <= 0)
 129.106 +            throw new IllegalArgumentException("Buffer size <= 0");
 129.107 +        this.out = out;
 129.108 +        cb = new char[sz];
 129.109 +        nChars = sz;
 129.110 +        nextChar = 0;
 129.111 +
 129.112 +        lineSeparator = "\n";
 129.113 +    }
 129.114 +
 129.115 +    /** Checks to make sure that the stream has not been closed */
 129.116 +    private void ensureOpen() throws IOException {
 129.117 +        if (out == null)
 129.118 +            throw new IOException("Stream closed");
 129.119 +    }
 129.120 +
 129.121 +    /**
 129.122 +     * Flushes the output buffer to the underlying character stream, without
 129.123 +     * flushing the stream itself.  This method is non-private only so that it
 129.124 +     * may be invoked by PrintStream.
 129.125 +     */
 129.126 +    void flushBuffer() throws IOException {
 129.127 +        synchronized (lock) {
 129.128 +            ensureOpen();
 129.129 +            if (nextChar == 0)
 129.130 +                return;
 129.131 +            out.write(cb, 0, nextChar);
 129.132 +            nextChar = 0;
 129.133 +        }
 129.134 +    }
 129.135 +
 129.136 +    /**
 129.137 +     * Writes a single character.
 129.138 +     *
 129.139 +     * @exception  IOException  If an I/O error occurs
 129.140 +     */
 129.141 +    public void write(int c) throws IOException {
 129.142 +        synchronized (lock) {
 129.143 +            ensureOpen();
 129.144 +            if (nextChar >= nChars)
 129.145 +                flushBuffer();
 129.146 +            cb[nextChar++] = (char) c;
 129.147 +        }
 129.148 +    }
 129.149 +
 129.150 +    /**
 129.151 +     * Our own little min method, to avoid loading java.lang.Math if we've run
 129.152 +     * out of file descriptors and we're trying to print a stack trace.
 129.153 +     */
 129.154 +    private int min(int a, int b) {
 129.155 +        if (a < b) return a;
 129.156 +        return b;
 129.157 +    }
 129.158 +
 129.159 +    /**
 129.160 +     * Writes a portion of an array of characters.
 129.161 +     *
 129.162 +     * <p> Ordinarily this method stores characters from the given array into
 129.163 +     * this stream's buffer, flushing the buffer to the underlying stream as
 129.164 +     * needed.  If the requested length is at least as large as the buffer,
 129.165 +     * however, then this method will flush the buffer and write the characters
 129.166 +     * directly to the underlying stream.  Thus redundant
 129.167 +     * <code>BufferedWriter</code>s will not copy data unnecessarily.
 129.168 +     *
 129.169 +     * @param  cbuf  A character array
 129.170 +     * @param  off   Offset from which to start reading characters
 129.171 +     * @param  len   Number of characters to write
 129.172 +     *
 129.173 +     * @exception  IOException  If an I/O error occurs
 129.174 +     */
 129.175 +    public void write(char cbuf[], int off, int len) throws IOException {
 129.176 +        synchronized (lock) {
 129.177 +            ensureOpen();
 129.178 +            if ((off < 0) || (off > cbuf.length) || (len < 0) ||
 129.179 +                ((off + len) > cbuf.length) || ((off + len) < 0)) {
 129.180 +                throw new IndexOutOfBoundsException();
 129.181 +            } else if (len == 0) {
 129.182 +                return;
 129.183 +            }
 129.184 +
 129.185 +            if (len >= nChars) {
 129.186 +                /* If the request length exceeds the size of the output buffer,
 129.187 +                   flush the buffer and then write the data directly.  In this
 129.188 +                   way buffered streams will cascade harmlessly. */
 129.189 +                flushBuffer();
 129.190 +                out.write(cbuf, off, len);
 129.191 +                return;
 129.192 +            }
 129.193 +
 129.194 +            int b = off, t = off + len;
 129.195 +            while (b < t) {
 129.196 +                int d = min(nChars - nextChar, t - b);
 129.197 +                System.arraycopy(cbuf, b, cb, nextChar, d);
 129.198 +                b += d;
 129.199 +                nextChar += d;
 129.200 +                if (nextChar >= nChars)
 129.201 +                    flushBuffer();
 129.202 +            }
 129.203 +        }
 129.204 +    }
 129.205 +
 129.206 +    /**
 129.207 +     * Writes a portion of a String.
 129.208 +     *
 129.209 +     * <p> If the value of the <tt>len</tt> parameter is negative then no
 129.210 +     * characters are written.  This is contrary to the specification of this
 129.211 +     * method in the {@linkplain java.io.Writer#write(java.lang.String,int,int)
 129.212 +     * superclass}, which requires that an {@link IndexOutOfBoundsException} be
 129.213 +     * thrown.
 129.214 +     *
 129.215 +     * @param  s     String to be written
 129.216 +     * @param  off   Offset from which to start reading characters
 129.217 +     * @param  len   Number of characters to be written
 129.218 +     *
 129.219 +     * @exception  IOException  If an I/O error occurs
 129.220 +     */
 129.221 +    public void write(String s, int off, int len) throws IOException {
 129.222 +        synchronized (lock) {
 129.223 +            ensureOpen();
 129.224 +
 129.225 +            int b = off, t = off + len;
 129.226 +            while (b < t) {
 129.227 +                int d = min(nChars - nextChar, t - b);
 129.228 +                s.getChars(b, b + d, cb, nextChar);
 129.229 +                b += d;
 129.230 +                nextChar += d;
 129.231 +                if (nextChar >= nChars)
 129.232 +                    flushBuffer();
 129.233 +            }
 129.234 +        }
 129.235 +    }
 129.236 +
 129.237 +    /**
 129.238 +     * Writes a line separator.  The line separator string is defined by the
 129.239 +     * system property <tt>line.separator</tt>, and is not necessarily a single
 129.240 +     * newline ('\n') character.
 129.241 +     *
 129.242 +     * @exception  IOException  If an I/O error occurs
 129.243 +     */
 129.244 +    public void newLine() throws IOException {
 129.245 +        write(lineSeparator);
 129.246 +    }
 129.247 +
 129.248 +    /**
 129.249 +     * Flushes the stream.
 129.250 +     *
 129.251 +     * @exception  IOException  If an I/O error occurs
 129.252 +     */
 129.253 +    public void flush() throws IOException {
 129.254 +        synchronized (lock) {
 129.255 +            flushBuffer();
 129.256 +            out.flush();
 129.257 +        }
 129.258 +    }
 129.259 +
 129.260 +    public void close() throws IOException {
 129.261 +        synchronized (lock) {
 129.262 +            if (out == null) {
 129.263 +                return;
 129.264 +            }
 129.265 +            try {
 129.266 +                flushBuffer();
 129.267 +            } finally {
 129.268 +                out.close();
 129.269 +                out = null;
 129.270 +                cb = null;
 129.271 +            }
 129.272 +        }
 129.273 +    }
 129.274 +}
   130.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   130.2 +++ b/rt/emul/compact/src/main/java/java/io/File.java	Mon Oct 07 14:20:58 2013 +0200
   130.3 @@ -0,0 +1,1927 @@
   130.4 +/*
   130.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
   130.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   130.7 + *
   130.8 + * This code is free software; you can redistribute it and/or modify it
   130.9 + * under the terms of the GNU General Public License version 2 only, as
  130.10 + * published by the Free Software Foundation.  Oracle designates this
  130.11 + * particular file as subject to the "Classpath" exception as provided
  130.12 + * by Oracle in the LICENSE file that accompanied this code.
  130.13 + *
  130.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  130.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  130.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  130.17 + * version 2 for more details (a copy is included in the LICENSE file that
  130.18 + * accompanied this code).
  130.19 + *
  130.20 + * You should have received a copy of the GNU General Public License version
  130.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  130.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  130.23 + *
  130.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  130.25 + * or visit www.oracle.com if you need additional information or have any
  130.26 + * questions.
  130.27 + */
  130.28 +
  130.29 +package java.io;
  130.30 +
  130.31 +import java.net.URI;
  130.32 +import java.net.URL;
  130.33 +import java.net.MalformedURLException;
  130.34 +import java.net.URISyntaxException;
  130.35 +
  130.36 +/**
  130.37 + * An abstract representation of file and directory pathnames.
  130.38 + *
  130.39 + * <p> User interfaces and operating systems use system-dependent <em>pathname
  130.40 + * strings</em> to name files and directories.  This class presents an
  130.41 + * abstract, system-independent view of hierarchical pathnames.  An
  130.42 + * <em>abstract pathname</em> has two components:
  130.43 + *
  130.44 + * <ol>
  130.45 + * <li> An optional system-dependent <em>prefix</em> string,
  130.46 + *      such as a disk-drive specifier, <code>"/"</code>&nbsp;for the UNIX root
  130.47 + *      directory, or <code>"\\\\"</code>&nbsp;for a Microsoft Windows UNC pathname, and
  130.48 + * <li> A sequence of zero or more string <em>names</em>.
  130.49 + * </ol>
  130.50 + *
  130.51 + * The first name in an abstract pathname may be a directory name or, in the
  130.52 + * case of Microsoft Windows UNC pathnames, a hostname.  Each subsequent name
  130.53 + * in an abstract pathname denotes a directory; the last name may denote
  130.54 + * either a directory or a file.  The <em>empty</em> abstract pathname has no
  130.55 + * prefix and an empty name sequence.
  130.56 + *
  130.57 + * <p> The conversion of a pathname string to or from an abstract pathname is
  130.58 + * inherently system-dependent.  When an abstract pathname is converted into a
  130.59 + * pathname string, each name is separated from the next by a single copy of
  130.60 + * the default <em>separator character</em>.  The default name-separator
  130.61 + * character is defined by the system property <code>file.separator</code>, and
  130.62 + * is made available in the public static fields <code>{@link
  130.63 + * #separator}</code> and <code>{@link #separatorChar}</code> of this class.
  130.64 + * When a pathname string is converted into an abstract pathname, the names
  130.65 + * within it may be separated by the default name-separator character or by any
  130.66 + * other name-separator character that is supported by the underlying system.
  130.67 + *
  130.68 + * <p> A pathname, whether abstract or in string form, may be either
  130.69 + * <em>absolute</em> or <em>relative</em>.  An absolute pathname is complete in
  130.70 + * that no other information is required in order to locate the file that it
  130.71 + * denotes.  A relative pathname, in contrast, must be interpreted in terms of
  130.72 + * information taken from some other pathname.  By default the classes in the
  130.73 + * <code>java.io</code> package always resolve relative pathnames against the
  130.74 + * current user directory.  This directory is named by the system property
  130.75 + * <code>user.dir</code>, and is typically the directory in which the Java
  130.76 + * virtual machine was invoked.
  130.77 + *
  130.78 + * <p> The <em>parent</em> of an abstract pathname may be obtained by invoking
  130.79 + * the {@link #getParent} method of this class and consists of the pathname's
  130.80 + * prefix and each name in the pathname's name sequence except for the last.
  130.81 + * Each directory's absolute pathname is an ancestor of any <tt>File</tt>
  130.82 + * object with an absolute abstract pathname which begins with the directory's
  130.83 + * absolute pathname.  For example, the directory denoted by the abstract
  130.84 + * pathname <tt>"/usr"</tt> is an ancestor of the directory denoted by the
  130.85 + * pathname <tt>"/usr/local/bin"</tt>.
  130.86 + *
  130.87 + * <p> The prefix concept is used to handle root directories on UNIX platforms,
  130.88 + * and drive specifiers, root directories and UNC pathnames on Microsoft Windows platforms,
  130.89 + * as follows:
  130.90 + *
  130.91 + * <ul>
  130.92 + *
  130.93 + * <li> For UNIX platforms, the prefix of an absolute pathname is always
  130.94 + * <code>"/"</code>.  Relative pathnames have no prefix.  The abstract pathname
  130.95 + * denoting the root directory has the prefix <code>"/"</code> and an empty
  130.96 + * name sequence.
  130.97 + *
  130.98 + * <li> For Microsoft Windows platforms, the prefix of a pathname that contains a drive
  130.99 + * specifier consists of the drive letter followed by <code>":"</code> and
 130.100 + * possibly followed by <code>"\\"</code> if the pathname is absolute.  The
 130.101 + * prefix of a UNC pathname is <code>"\\\\"</code>; the hostname and the share
 130.102 + * name are the first two names in the name sequence.  A relative pathname that
 130.103 + * does not specify a drive has no prefix.
 130.104 + *
 130.105 + * </ul>
 130.106 + *
 130.107 + * <p> Instances of this class may or may not denote an actual file-system
 130.108 + * object such as a file or a directory.  If it does denote such an object
 130.109 + * then that object resides in a <i>partition</i>.  A partition is an
 130.110 + * operating system-specific portion of storage for a file system.  A single
 130.111 + * storage device (e.g. a physical disk-drive, flash memory, CD-ROM) may
 130.112 + * contain multiple partitions.  The object, if any, will reside on the
 130.113 + * partition <a name="partName">named</a> by some ancestor of the absolute
 130.114 + * form of this pathname.
 130.115 + *
 130.116 + * <p> A file system may implement restrictions to certain operations on the
 130.117 + * actual file-system object, such as reading, writing, and executing.  These
 130.118 + * restrictions are collectively known as <i>access permissions</i>.  The file
 130.119 + * system may have multiple sets of access permissions on a single object.
 130.120 + * For example, one set may apply to the object's <i>owner</i>, and another
 130.121 + * may apply to all other users.  The access permissions on an object may
 130.122 + * cause some methods in this class to fail.
 130.123 + *
 130.124 + * <p> Instances of the <code>File</code> class are immutable; that is, once
 130.125 + * created, the abstract pathname represented by a <code>File</code> object
 130.126 + * will never change.
 130.127 + *
 130.128 + * <h4>Interoperability with {@code java.nio.file} package</h4>
 130.129 + *
 130.130 + * <p> The <a href="../../java/nio/file/package-summary.html">{@code java.nio.file}</a>
 130.131 + * package defines interfaces and classes for the Java virtual machine to access
 130.132 + * files, file attributes, and file systems. This API may be used to overcome
 130.133 + * many of the limitations of the {@code java.io.File} class.
 130.134 + * The {@link #toPath toPath} method may be used to obtain a {@link
 130.135 + * Path} that uses the abstract path represented by a {@code File} object to
 130.136 + * locate a file. The resulting {@code Path} may be used with the {@link
 130.137 + * java.nio.file.Files} class to provide more efficient and extensive access to
 130.138 + * additional file operations, file attributes, and I/O exceptions to help
 130.139 + * diagnose errors when an operation on a file fails.
 130.140 + *
 130.141 + * @author  unascribed
 130.142 + * @since   JDK1.0
 130.143 + */
 130.144 +
 130.145 +public class File
 130.146 +    implements Serializable, Comparable<File>
 130.147 +{
 130.148 +
 130.149 +    /**
 130.150 +     * The FileSystem object representing the platform's local file system.
 130.151 +     */
 130.152 +    static private FileSystem fs = new FileSystem();
 130.153 +    private static class FileSystem {
 130.154 +
 130.155 +        private char getSeparator() {
 130.156 +            return '/';
 130.157 +        }
 130.158 +
 130.159 +        private String resolve(String path, String child) {
 130.160 +            return path + '/' + child;
 130.161 +        }
 130.162 +
 130.163 +        private String normalize(String pathname) {
 130.164 +            return pathname;
 130.165 +        }
 130.166 +
 130.167 +        private int prefixLength(String path) {
 130.168 +            return 0;
 130.169 +        }
 130.170 +
 130.171 +        private String getDefaultParent() {
 130.172 +            return "/";
 130.173 +        }
 130.174 +
 130.175 +        private String fromURIPath(String p) {
 130.176 +            return p;
 130.177 +        }
 130.178 +
 130.179 +        private boolean isAbsolute(File aThis) {
 130.180 +            return aThis.getPath().startsWith("/");
 130.181 +        }
 130.182 +
 130.183 +        private int compare(File one, File two) {
 130.184 +            return one.getPath().compareTo(two.getPath());
 130.185 +        }
 130.186 +
 130.187 +        private int hashCode(File aThis) {
 130.188 +            return aThis.getPath().hashCode();
 130.189 +        }
 130.190 +
 130.191 +        private char getPathSeparator() {
 130.192 +            return ':';
 130.193 +        }
 130.194 +        
 130.195 +    }
 130.196 +
 130.197 +    /**
 130.198 +     * This abstract pathname's normalized pathname string.  A normalized
 130.199 +     * pathname string uses the default name-separator character and does not
 130.200 +     * contain any duplicate or redundant separators.
 130.201 +     *
 130.202 +     * @serial
 130.203 +     */
 130.204 +    private String path;
 130.205 +
 130.206 +    /**
 130.207 +     * The length of this abstract pathname's prefix, or zero if it has no
 130.208 +     * prefix.
 130.209 +     */
 130.210 +    private transient int prefixLength;
 130.211 +
 130.212 +    /**
 130.213 +     * Returns the length of this abstract pathname's prefix.
 130.214 +     * For use by FileSystem classes.
 130.215 +     */
 130.216 +    int getPrefixLength() {
 130.217 +        return prefixLength;
 130.218 +    }
 130.219 +
 130.220 +    /**
 130.221 +     * The system-dependent default name-separator character.  This field is
 130.222 +     * initialized to contain the first character of the value of the system
 130.223 +     * property <code>file.separator</code>.  On UNIX systems the value of this
 130.224 +     * field is <code>'/'</code>; on Microsoft Windows systems it is <code>'\\'</code>.
 130.225 +     *
 130.226 +     * @see     java.lang.System#getProperty(java.lang.String)
 130.227 +     */
 130.228 +    public static final char separatorChar = fs.getSeparator();
 130.229 +
 130.230 +    /**
 130.231 +     * The system-dependent default name-separator character, represented as a
 130.232 +     * string for convenience.  This string contains a single character, namely
 130.233 +     * <code>{@link #separatorChar}</code>.
 130.234 +     */
 130.235 +    public static final String separator = "" + separatorChar;
 130.236 +
 130.237 +    /**
 130.238 +     * The system-dependent path-separator character.  This field is
 130.239 +     * initialized to contain the first character of the value of the system
 130.240 +     * property <code>path.separator</code>.  This character is used to
 130.241 +     * separate filenames in a sequence of files given as a <em>path list</em>.
 130.242 +     * On UNIX systems, this character is <code>':'</code>; on Microsoft Windows systems it
 130.243 +     * is <code>';'</code>.
 130.244 +     *
 130.245 +     * @see     java.lang.System#getProperty(java.lang.String)
 130.246 +     */
 130.247 +    public static final char pathSeparatorChar = fs.getPathSeparator();
 130.248 +
 130.249 +    /**
 130.250 +     * The system-dependent path-separator character, represented as a string
 130.251 +     * for convenience.  This string contains a single character, namely
 130.252 +     * <code>{@link #pathSeparatorChar}</code>.
 130.253 +     */
 130.254 +    public static final String pathSeparator = "" + pathSeparatorChar;
 130.255 +
 130.256 +
 130.257 +    /* -- Constructors -- */
 130.258 +
 130.259 +    /**
 130.260 +     * Internal constructor for already-normalized pathname strings.
 130.261 +     */
 130.262 +    private File(String pathname, int prefixLength) {
 130.263 +        this.path = pathname;
 130.264 +        this.prefixLength = prefixLength;
 130.265 +    }
 130.266 +
 130.267 +    /**
 130.268 +     * Internal constructor for already-normalized pathname strings.
 130.269 +     * The parameter order is used to disambiguate this method from the
 130.270 +     * public(File, String) constructor.
 130.271 +     */
 130.272 +    private File(String child, File parent) {
 130.273 +        assert parent.path != null;
 130.274 +        assert (!parent.path.equals(""));
 130.275 +        this.path = fs.resolve(parent.path, child);
 130.276 +        this.prefixLength = parent.prefixLength;
 130.277 +    }
 130.278 +
 130.279 +    /**
 130.280 +     * Creates a new <code>File</code> instance by converting the given
 130.281 +     * pathname string into an abstract pathname.  If the given string is
 130.282 +     * the empty string, then the result is the empty abstract pathname.
 130.283 +     *
 130.284 +     * @param   pathname  A pathname string
 130.285 +     * @throws  NullPointerException
 130.286 +     *          If the <code>pathname</code> argument is <code>null</code>
 130.287 +     */
 130.288 +    public File(String pathname) {
 130.289 +        if (pathname == null) {
 130.290 +            throw new NullPointerException();
 130.291 +        }
 130.292 +        this.path = fs.normalize(pathname);
 130.293 +        this.prefixLength = fs.prefixLength(this.path);
 130.294 +    }
 130.295 +
 130.296 +    /* Note: The two-argument File constructors do not interpret an empty
 130.297 +       parent abstract pathname as the current user directory.  An empty parent
 130.298 +       instead causes the child to be resolved against the system-dependent
 130.299 +       directory defined by the FileSystem.getDefaultParent method.  On Unix
 130.300 +       this default is "/", while on Microsoft Windows it is "\\".  This is required for
 130.301 +       compatibility with the original behavior of this class. */
 130.302 +
 130.303 +    /**
 130.304 +     * Creates a new <code>File</code> instance from a parent pathname string
 130.305 +     * and a child pathname string.
 130.306 +     *
 130.307 +     * <p> If <code>parent</code> is <code>null</code> then the new
 130.308 +     * <code>File</code> instance is created as if by invoking the
 130.309 +     * single-argument <code>File</code> constructor on the given
 130.310 +     * <code>child</code> pathname string.
 130.311 +     *
 130.312 +     * <p> Otherwise the <code>parent</code> pathname string is taken to denote
 130.313 +     * a directory, and the <code>child</code> pathname string is taken to
 130.314 +     * denote either a directory or a file.  If the <code>child</code> pathname
 130.315 +     * string is absolute then it is converted into a relative pathname in a
 130.316 +     * system-dependent way.  If <code>parent</code> is the empty string then
 130.317 +     * the new <code>File</code> instance is created by converting
 130.318 +     * <code>child</code> into an abstract pathname and resolving the result
 130.319 +     * against a system-dependent default directory.  Otherwise each pathname
 130.320 +     * string is converted into an abstract pathname and the child abstract
 130.321 +     * pathname is resolved against the parent.
 130.322 +     *
 130.323 +     * @param   parent  The parent pathname string
 130.324 +     * @param   child   The child pathname string
 130.325 +     * @throws  NullPointerException
 130.326 +     *          If <code>child</code> is <code>null</code>
 130.327 +     */
 130.328 +    public File(String parent, String child) {
 130.329 +        if (child == null) {
 130.330 +            throw new NullPointerException();
 130.331 +        }
 130.332 +        if (parent != null) {
 130.333 +            if (parent.equals("")) {
 130.334 +                this.path = fs.resolve(fs.getDefaultParent(),
 130.335 +                                       fs.normalize(child));
 130.336 +            } else {
 130.337 +                this.path = fs.resolve(fs.normalize(parent),
 130.338 +                                       fs.normalize(child));
 130.339 +            }
 130.340 +        } else {
 130.341 +            this.path = fs.normalize(child);
 130.342 +        }
 130.343 +        this.prefixLength = fs.prefixLength(this.path);
 130.344 +    }
 130.345 +
 130.346 +    /**
 130.347 +     * Creates a new <code>File</code> instance from a parent abstract
 130.348 +     * pathname and a child pathname string.
 130.349 +     *
 130.350 +     * <p> If <code>parent</code> is <code>null</code> then the new
 130.351 +     * <code>File</code> instance is created as if by invoking the
 130.352 +     * single-argument <code>File</code> constructor on the given
 130.353 +     * <code>child</code> pathname string.
 130.354 +     *
 130.355 +     * <p> Otherwise the <code>parent</code> abstract pathname is taken to
 130.356 +     * denote a directory, and the <code>child</code> pathname string is taken
 130.357 +     * to denote either a directory or a file.  If the <code>child</code>
 130.358 +     * pathname string is absolute then it is converted into a relative
 130.359 +     * pathname in a system-dependent way.  If <code>parent</code> is the empty
 130.360 +     * abstract pathname then the new <code>File</code> instance is created by
 130.361 +     * converting <code>child</code> into an abstract pathname and resolving
 130.362 +     * the result against a system-dependent default directory.  Otherwise each
 130.363 +     * pathname string is converted into an abstract pathname and the child
 130.364 +     * abstract pathname is resolved against the parent.
 130.365 +     *
 130.366 +     * @param   parent  The parent abstract pathname
 130.367 +     * @param   child   The child pathname string
 130.368 +     * @throws  NullPointerException
 130.369 +     *          If <code>child</code> is <code>null</code>
 130.370 +     */
 130.371 +    public File(File parent, String child) {
 130.372 +        if (child == null) {
 130.373 +            throw new NullPointerException();
 130.374 +        }
 130.375 +        if (parent != null) {
 130.376 +            if (parent.path.equals("")) {
 130.377 +                this.path = fs.resolve(fs.getDefaultParent(),
 130.378 +                                       fs.normalize(child));
 130.379 +            } else {
 130.380 +                this.path = fs.resolve(parent.path,
 130.381 +                                       fs.normalize(child));
 130.382 +            }
 130.383 +        } else {
 130.384 +            this.path = fs.normalize(child);
 130.385 +        }
 130.386 +        this.prefixLength = fs.prefixLength(this.path);
 130.387 +    }
 130.388 +
 130.389 +    /**
 130.390 +     * Creates a new <tt>File</tt> instance by converting the given
 130.391 +     * <tt>file:</tt> URI into an abstract pathname.
 130.392 +     *
 130.393 +     * <p> The exact form of a <tt>file:</tt> URI is system-dependent, hence
 130.394 +     * the transformation performed by this constructor is also
 130.395 +     * system-dependent.
 130.396 +     *
 130.397 +     * <p> For a given abstract pathname <i>f</i> it is guaranteed that
 130.398 +     *
 130.399 +     * <blockquote><tt>
 130.400 +     * new File(</tt><i>&nbsp;f</i><tt>.{@link #toURI() toURI}()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
 130.401 +     * </tt></blockquote>
 130.402 +     *
 130.403 +     * so long as the original abstract pathname, the URI, and the new abstract
 130.404 +     * pathname are all created in (possibly different invocations of) the same
 130.405 +     * Java virtual machine.  This relationship typically does not hold,
 130.406 +     * however, when a <tt>file:</tt> URI that is created in a virtual machine
 130.407 +     * on one operating system is converted into an abstract pathname in a
 130.408 +     * virtual machine on a different operating system.
 130.409 +     *
 130.410 +     * @param  uri
 130.411 +     *         An absolute, hierarchical URI with a scheme equal to
 130.412 +     *         <tt>"file"</tt>, a non-empty path component, and undefined
 130.413 +     *         authority, query, and fragment components
 130.414 +     *
 130.415 +     * @throws  NullPointerException
 130.416 +     *          If <tt>uri</tt> is <tt>null</tt>
 130.417 +     *
 130.418 +     * @throws  IllegalArgumentException
 130.419 +     *          If the preconditions on the parameter do not hold
 130.420 +     *
 130.421 +     * @see #toURI()
 130.422 +     * @see java.net.URI
 130.423 +     * @since 1.4
 130.424 +     */
 130.425 +    public File(URI uri) {
 130.426 +
 130.427 +        // Check our many preconditions
 130.428 +        if (!uri.isAbsolute())
 130.429 +            throw new IllegalArgumentException("URI is not absolute");
 130.430 +        if (uri.isOpaque())
 130.431 +            throw new IllegalArgumentException("URI is not hierarchical");
 130.432 +        String scheme = uri.getScheme();
 130.433 +        if ((scheme == null) || !scheme.equalsIgnoreCase("file"))
 130.434 +            throw new IllegalArgumentException("URI scheme is not \"file\"");
 130.435 +        if (uri.getAuthority() != null)
 130.436 +            throw new IllegalArgumentException("URI has an authority component");
 130.437 +        if (uri.getFragment() != null)
 130.438 +            throw new IllegalArgumentException("URI has a fragment component");
 130.439 +        if (uri.getQuery() != null)
 130.440 +            throw new IllegalArgumentException("URI has a query component");
 130.441 +        String p = uri.getPath();
 130.442 +        if (p.equals(""))
 130.443 +            throw new IllegalArgumentException("URI path component is empty");
 130.444 +
 130.445 +        // Okay, now initialize
 130.446 +        p = fs.fromURIPath(p);
 130.447 +        if (File.separatorChar != '/')
 130.448 +            p = p.replace('/', File.separatorChar);
 130.449 +        this.path = fs.normalize(p);
 130.450 +        this.prefixLength = fs.prefixLength(this.path);
 130.451 +    }
 130.452 +
 130.453 +
 130.454 +    /* -- Path-component accessors -- */
 130.455 +
 130.456 +    /**
 130.457 +     * Returns the name of the file or directory denoted by this abstract
 130.458 +     * pathname.  This is just the last name in the pathname's name
 130.459 +     * sequence.  If the pathname's name sequence is empty, then the empty
 130.460 +     * string is returned.
 130.461 +     *
 130.462 +     * @return  The name of the file or directory denoted by this abstract
 130.463 +     *          pathname, or the empty string if this pathname's name sequence
 130.464 +     *          is empty
 130.465 +     */
 130.466 +    public String getName() {
 130.467 +        int index = path.lastIndexOf(separatorChar);
 130.468 +        if (index < prefixLength) return path.substring(prefixLength);
 130.469 +        return path.substring(index + 1);
 130.470 +    }
 130.471 +
 130.472 +    /**
 130.473 +     * Returns the pathname string of this abstract pathname's parent, or
 130.474 +     * <code>null</code> if this pathname does not name a parent directory.
 130.475 +     *
 130.476 +     * <p> The <em>parent</em> of an abstract pathname consists of the
 130.477 +     * pathname's prefix, if any, and each name in the pathname's name
 130.478 +     * sequence except for the last.  If the name sequence is empty then
 130.479 +     * the pathname does not name a parent directory.
 130.480 +     *
 130.481 +     * @return  The pathname string of the parent directory named by this
 130.482 +     *          abstract pathname, or <code>null</code> if this pathname
 130.483 +     *          does not name a parent
 130.484 +     */
 130.485 +    public String getParent() {
 130.486 +        int index = path.lastIndexOf(separatorChar);
 130.487 +        if (index < prefixLength) {
 130.488 +            if ((prefixLength > 0) && (path.length() > prefixLength))
 130.489 +                return path.substring(0, prefixLength);
 130.490 +            return null;
 130.491 +        }
 130.492 +        return path.substring(0, index);
 130.493 +    }
 130.494 +
 130.495 +    /**
 130.496 +     * Returns the abstract pathname of this abstract pathname's parent,
 130.497 +     * or <code>null</code> if this pathname does not name a parent
 130.498 +     * directory.
 130.499 +     *
 130.500 +     * <p> The <em>parent</em> of an abstract pathname consists of the
 130.501 +     * pathname's prefix, if any, and each name in the pathname's name
 130.502 +     * sequence except for the last.  If the name sequence is empty then
 130.503 +     * the pathname does not name a parent directory.
 130.504 +     *
 130.505 +     * @return  The abstract pathname of the parent directory named by this
 130.506 +     *          abstract pathname, or <code>null</code> if this pathname
 130.507 +     *          does not name a parent
 130.508 +     *
 130.509 +     * @since 1.2
 130.510 +     */
 130.511 +    public File getParentFile() {
 130.512 +        String p = this.getParent();
 130.513 +        if (p == null) return null;
 130.514 +        return new File(p, this.prefixLength);
 130.515 +    }
 130.516 +
 130.517 +    /**
 130.518 +     * Converts this abstract pathname into a pathname string.  The resulting
 130.519 +     * string uses the {@link #separator default name-separator character} to
 130.520 +     * separate the names in the name sequence.
 130.521 +     *
 130.522 +     * @return  The string form of this abstract pathname
 130.523 +     */
 130.524 +    public String getPath() {
 130.525 +        return path;
 130.526 +    }
 130.527 +
 130.528 +
 130.529 +    /* -- Path operations -- */
 130.530 +
 130.531 +    /**
 130.532 +     * Tests whether this abstract pathname is absolute.  The definition of
 130.533 +     * absolute pathname is system dependent.  On UNIX systems, a pathname is
 130.534 +     * absolute if its prefix is <code>"/"</code>.  On Microsoft Windows systems, a
 130.535 +     * pathname is absolute if its prefix is a drive specifier followed by
 130.536 +     * <code>"\\"</code>, or if its prefix is <code>"\\\\"</code>.
 130.537 +     *
 130.538 +     * @return  <code>true</code> if this abstract pathname is absolute,
 130.539 +     *          <code>false</code> otherwise
 130.540 +     */
 130.541 +    public boolean isAbsolute() {
 130.542 +        return fs.isAbsolute(this);
 130.543 +    }
 130.544 +
 130.545 +    /**
 130.546 +     * Returns the absolute pathname string of this abstract pathname.
 130.547 +     *
 130.548 +     * <p> If this abstract pathname is already absolute, then the pathname
 130.549 +     * string is simply returned as if by the <code>{@link #getPath}</code>
 130.550 +     * method.  If this abstract pathname is the empty abstract pathname then
 130.551 +     * the pathname string of the current user directory, which is named by the
 130.552 +     * system property <code>user.dir</code>, is returned.  Otherwise this
 130.553 +     * pathname is resolved in a system-dependent way.  On UNIX systems, a
 130.554 +     * relative pathname is made absolute by resolving it against the current
 130.555 +     * user directory.  On Microsoft Windows systems, a relative pathname is made absolute
 130.556 +     * by resolving it against the current directory of the drive named by the
 130.557 +     * pathname, if any; if not, it is resolved against the current user
 130.558 +     * directory.
 130.559 +     *
 130.560 +     * @return  The absolute pathname string denoting the same file or
 130.561 +     *          directory as this abstract pathname
 130.562 +     *
 130.563 +     * @throws  SecurityException
 130.564 +     *          If a required system property value cannot be accessed.
 130.565 +     *
 130.566 +     * @see     java.io.File#isAbsolute()
 130.567 +     */
 130.568 +    public String getAbsolutePath() {
 130.569 +        throw new SecurityException();
 130.570 +    }
 130.571 +
 130.572 +    /**
 130.573 +     * Returns the absolute form of this abstract pathname.  Equivalent to
 130.574 +     * <code>new&nbsp;File(this.{@link #getAbsolutePath})</code>.
 130.575 +     *
 130.576 +     * @return  The absolute abstract pathname denoting the same file or
 130.577 +     *          directory as this abstract pathname
 130.578 +     *
 130.579 +     * @throws  SecurityException
 130.580 +     *          If a required system property value cannot be accessed.
 130.581 +     *
 130.582 +     * @since 1.2
 130.583 +     */
 130.584 +    public File getAbsoluteFile() {
 130.585 +        String absPath = getAbsolutePath();
 130.586 +        return new File(absPath, fs.prefixLength(absPath));
 130.587 +    }
 130.588 +
 130.589 +    /**
 130.590 +     * Returns the canonical pathname string of this abstract pathname.
 130.591 +     *
 130.592 +     * <p> A canonical pathname is both absolute and unique.  The precise
 130.593 +     * definition of canonical form is system-dependent.  This method first
 130.594 +     * converts this pathname to absolute form if necessary, as if by invoking the
 130.595 +     * {@link #getAbsolutePath} method, and then maps it to its unique form in a
 130.596 +     * system-dependent way.  This typically involves removing redundant names
 130.597 +     * such as <tt>"."</tt> and <tt>".."</tt> from the pathname, resolving
 130.598 +     * symbolic links (on UNIX platforms), and converting drive letters to a
 130.599 +     * standard case (on Microsoft Windows platforms).
 130.600 +     *
 130.601 +     * <p> Every pathname that denotes an existing file or directory has a
 130.602 +     * unique canonical form.  Every pathname that denotes a nonexistent file
 130.603 +     * or directory also has a unique canonical form.  The canonical form of
 130.604 +     * the pathname of a nonexistent file or directory may be different from
 130.605 +     * the canonical form of the same pathname after the file or directory is
 130.606 +     * created.  Similarly, the canonical form of the pathname of an existing
 130.607 +     * file or directory may be different from the canonical form of the same
 130.608 +     * pathname after the file or directory is deleted.
 130.609 +     *
 130.610 +     * @return  The canonical pathname string denoting the same file or
 130.611 +     *          directory as this abstract pathname
 130.612 +     *
 130.613 +     * @throws  IOException
 130.614 +     *          If an I/O error occurs, which is possible because the
 130.615 +     *          construction of the canonical pathname may require
 130.616 +     *          filesystem queries
 130.617 +     *
 130.618 +     * @throws  SecurityException
 130.619 +     *          If a required system property value cannot be accessed, or
 130.620 +     *          if a security manager exists and its <code>{@link
 130.621 +     *          java.lang.SecurityManager#checkRead}</code> method denies
 130.622 +     *          read access to the file
 130.623 +     *
 130.624 +     * @since   JDK1.1
 130.625 +     * @see     Path#toRealPath
 130.626 +     */
 130.627 +    public String getCanonicalPath() throws IOException {
 130.628 +        throw new SecurityException();
 130.629 +    }
 130.630 +
 130.631 +    /**
 130.632 +     * Returns the canonical form of this abstract pathname.  Equivalent to
 130.633 +     * <code>new&nbsp;File(this.{@link #getCanonicalPath})</code>.
 130.634 +     *
 130.635 +     * @return  The canonical pathname string denoting the same file or
 130.636 +     *          directory as this abstract pathname
 130.637 +     *
 130.638 +     * @throws  IOException
 130.639 +     *          If an I/O error occurs, which is possible because the
 130.640 +     *          construction of the canonical pathname may require
 130.641 +     *          filesystem queries
 130.642 +     *
 130.643 +     * @throws  SecurityException
 130.644 +     *          If a required system property value cannot be accessed, or
 130.645 +     *          if a security manager exists and its <code>{@link
 130.646 +     *          java.lang.SecurityManager#checkRead}</code> method denies
 130.647 +     *          read access to the file
 130.648 +     *
 130.649 +     * @since 1.2
 130.650 +     * @see     Path#toRealPath
 130.651 +     */
 130.652 +    public File getCanonicalFile() throws IOException {
 130.653 +        String canonPath = getCanonicalPath();
 130.654 +        return new File(canonPath, fs.prefixLength(canonPath));
 130.655 +    }
 130.656 +
 130.657 +    private static String slashify(String path, boolean isDirectory) {
 130.658 +        String p = path;
 130.659 +        if (File.separatorChar != '/')
 130.660 +            p = p.replace(File.separatorChar, '/');
 130.661 +        if (!p.startsWith("/"))
 130.662 +            p = "/" + p;
 130.663 +        if (!p.endsWith("/") && isDirectory)
 130.664 +            p = p + "/";
 130.665 +        return p;
 130.666 +    }
 130.667 +
 130.668 +    /**
 130.669 +     * Converts this abstract pathname into a <code>file:</code> URL.  The
 130.670 +     * exact form of the URL is system-dependent.  If it can be determined that
 130.671 +     * the file denoted by this abstract pathname is a directory, then the
 130.672 +     * resulting URL will end with a slash.
 130.673 +     *
 130.674 +     * @return  A URL object representing the equivalent file URL
 130.675 +     *
 130.676 +     * @throws  MalformedURLException
 130.677 +     *          If the path cannot be parsed as a URL
 130.678 +     *
 130.679 +     * @see     #toURI()
 130.680 +     * @see     java.net.URI
 130.681 +     * @see     java.net.URI#toURL()
 130.682 +     * @see     java.net.URL
 130.683 +     * @since   1.2
 130.684 +     *
 130.685 +     * @deprecated This method does not automatically escape characters that
 130.686 +     * are illegal in URLs.  It is recommended that new code convert an
 130.687 +     * abstract pathname into a URL by first converting it into a URI, via the
 130.688 +     * {@link #toURI() toURI} method, and then converting the URI into a URL
 130.689 +     * via the {@link java.net.URI#toURL() URI.toURL} method.
 130.690 +     */
 130.691 +    @Deprecated
 130.692 +    public URL toURL() throws MalformedURLException {
 130.693 +        return new URL("file", "", slashify(getAbsolutePath(), isDirectory()));
 130.694 +    }
 130.695 +
 130.696 +    /**
 130.697 +     * Constructs a <tt>file:</tt> URI that represents this abstract pathname.
 130.698 +     *
 130.699 +     * <p> The exact form of the URI is system-dependent.  If it can be
 130.700 +     * determined that the file denoted by this abstract pathname is a
 130.701 +     * directory, then the resulting URI will end with a slash.
 130.702 +     *
 130.703 +     * <p> For a given abstract pathname <i>f</i>, it is guaranteed that
 130.704 +     *
 130.705 +     * <blockquote><tt>
 130.706 +     * new {@link #File(java.net.URI) File}(</tt><i>&nbsp;f</i><tt>.toURI()).equals(</tt><i>&nbsp;f</i><tt>.{@link #getAbsoluteFile() getAbsoluteFile}())
 130.707 +     * </tt></blockquote>
 130.708 +     *
 130.709 +     * so long as the original abstract pathname, the URI, and the new abstract
 130.710 +     * pathname are all created in (possibly different invocations of) the same
 130.711 +     * Java virtual machine.  Due to the system-dependent nature of abstract
 130.712 +     * pathnames, however, this relationship typically does not hold when a
 130.713 +     * <tt>file:</tt> URI that is created in a virtual machine on one operating
 130.714 +     * system is converted into an abstract pathname in a virtual machine on a
 130.715 +     * different operating system.
 130.716 +     *
 130.717 +     * <p> Note that when this abstract pathname represents a UNC pathname then
 130.718 +     * all components of the UNC (including the server name component) are encoded
 130.719 +     * in the {@code URI} path. The authority component is undefined, meaning
 130.720 +     * that it is represented as {@code null}. The {@link Path} class defines the
 130.721 +     * {@link Path#toUri toUri} method to encode the server name in the authority
 130.722 +     * component of the resulting {@code URI}. The {@link #toPath toPath} method
 130.723 +     * may be used to obtain a {@code Path} representing this abstract pathname.
 130.724 +     *
 130.725 +     * @return  An absolute, hierarchical URI with a scheme equal to
 130.726 +     *          <tt>"file"</tt>, a path representing this abstract pathname,
 130.727 +     *          and undefined authority, query, and fragment components
 130.728 +     * @throws SecurityException If a required system property value cannot
 130.729 +     * be accessed.
 130.730 +     *
 130.731 +     * @see #File(java.net.URI)
 130.732 +     * @see java.net.URI
 130.733 +     * @see java.net.URI#toURL()
 130.734 +     * @since 1.4
 130.735 +     */
 130.736 +    public URI toURI() {
 130.737 +        try {
 130.738 +            File f = getAbsoluteFile();
 130.739 +            String sp = slashify(f.getPath(), f.isDirectory());
 130.740 +            if (sp.startsWith("//"))
 130.741 +                sp = "//" + sp;
 130.742 +            return new URI("file", null, sp, null);
 130.743 +        } catch (URISyntaxException x) {
 130.744 +            throw new Error(x);         // Can't happen
 130.745 +        }
 130.746 +    }
 130.747 +
 130.748 +
 130.749 +    /* -- Attribute accessors -- */
 130.750 +
 130.751 +    /**
 130.752 +     * Tests whether the application can read the file denoted by this
 130.753 +     * abstract pathname.
 130.754 +     *
 130.755 +     * @return  <code>true</code> if and only if the file specified by this
 130.756 +     *          abstract pathname exists <em>and</em> can be read by the
 130.757 +     *          application; <code>false</code> otherwise
 130.758 +     *
 130.759 +     * @throws  SecurityException
 130.760 +     *          If a security manager exists and its <code>{@link
 130.761 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.762 +     *          method denies read access to the file
 130.763 +     */
 130.764 +    public boolean canRead() {
 130.765 +        throw new SecurityException();
 130.766 +    }
 130.767 +
 130.768 +    /**
 130.769 +     * Tests whether the application can modify the file denoted by this
 130.770 +     * abstract pathname.
 130.771 +     *
 130.772 +     * @return  <code>true</code> if and only if the file system actually
 130.773 +     *          contains a file denoted by this abstract pathname <em>and</em>
 130.774 +     *          the application is allowed to write to the file;
 130.775 +     *          <code>false</code> otherwise.
 130.776 +     *
 130.777 +     * @throws  SecurityException
 130.778 +     *          If a security manager exists and its <code>{@link
 130.779 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
 130.780 +     *          method denies write access to the file
 130.781 +     */
 130.782 +    public boolean canWrite() {
 130.783 +        throw new SecurityException();
 130.784 +    }
 130.785 +
 130.786 +    /**
 130.787 +     * Tests whether the file or directory denoted by this abstract pathname
 130.788 +     * exists.
 130.789 +     *
 130.790 +     * @return  <code>true</code> if and only if the file or directory denoted
 130.791 +     *          by this abstract pathname exists; <code>false</code> otherwise
 130.792 +     *
 130.793 +     * @throws  SecurityException
 130.794 +     *          If a security manager exists and its <code>{@link
 130.795 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.796 +     *          method denies read access to the file or directory
 130.797 +     */
 130.798 +    public boolean exists() {
 130.799 +        throw new SecurityException();
 130.800 +    }
 130.801 +
 130.802 +    /**
 130.803 +     * Tests whether the file denoted by this abstract pathname is a
 130.804 +     * directory.
 130.805 +     *
 130.806 +     * <p> Where it is required to distinguish an I/O exception from the case
 130.807 +     * that the file is not a directory, or where several attributes of the
 130.808 +     * same file are required at the same time, then the {@link
 130.809 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 130.810 +     * Files.readAttributes} method may be used.
 130.811 +     *
 130.812 +     * @return <code>true</code> if and only if the file denoted by this
 130.813 +     *          abstract pathname exists <em>and</em> is a directory;
 130.814 +     *          <code>false</code> otherwise
 130.815 +     *
 130.816 +     * @throws  SecurityException
 130.817 +     *          If a security manager exists and its <code>{@link
 130.818 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.819 +     *          method denies read access to the file
 130.820 +     */
 130.821 +    public boolean isDirectory() {
 130.822 +        throw new SecurityException();
 130.823 +    }
 130.824 +
 130.825 +    /**
 130.826 +     * Tests whether the file denoted by this abstract pathname is a normal
 130.827 +     * file.  A file is <em>normal</em> if it is not a directory and, in
 130.828 +     * addition, satisfies other system-dependent criteria.  Any non-directory
 130.829 +     * file created by a Java application is guaranteed to be a normal file.
 130.830 +     *
 130.831 +     * <p> Where it is required to distinguish an I/O exception from the case
 130.832 +     * that the file is not a normal file, or where several attributes of the
 130.833 +     * same file are required at the same time, then the {@link
 130.834 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 130.835 +     * Files.readAttributes} method may be used.
 130.836 +     *
 130.837 +     * @return  <code>true</code> if and only if the file denoted by this
 130.838 +     *          abstract pathname exists <em>and</em> is a normal file;
 130.839 +     *          <code>false</code> otherwise
 130.840 +     *
 130.841 +     * @throws  SecurityException
 130.842 +     *          If a security manager exists and its <code>{@link
 130.843 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.844 +     *          method denies read access to the file
 130.845 +     */
 130.846 +    public boolean isFile() {
 130.847 +        throw new SecurityException();
 130.848 +    }
 130.849 +
 130.850 +    /**
 130.851 +     * Tests whether the file named by this abstract pathname is a hidden
 130.852 +     * file.  The exact definition of <em>hidden</em> is system-dependent.  On
 130.853 +     * UNIX systems, a file is considered to be hidden if its name begins with
 130.854 +     * a period character (<code>'.'</code>).  On Microsoft Windows systems, a file is
 130.855 +     * considered to be hidden if it has been marked as such in the filesystem.
 130.856 +     *
 130.857 +     * @return  <code>true</code> if and only if the file denoted by this
 130.858 +     *          abstract pathname is hidden according to the conventions of the
 130.859 +     *          underlying platform
 130.860 +     *
 130.861 +     * @throws  SecurityException
 130.862 +     *          If a security manager exists and its <code>{@link
 130.863 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.864 +     *          method denies read access to the file
 130.865 +     *
 130.866 +     * @since 1.2
 130.867 +     */
 130.868 +    public boolean isHidden() {
 130.869 +        throw new SecurityException();
 130.870 +    }
 130.871 +
 130.872 +    /**
 130.873 +     * Returns the time that the file denoted by this abstract pathname was
 130.874 +     * last modified.
 130.875 +     *
 130.876 +     * <p> Where it is required to distinguish an I/O exception from the case
 130.877 +     * where {@code 0L} is returned, or where several attributes of the
 130.878 +     * same file are required at the same time, or where the time of last
 130.879 +     * access or the creation time are required, then the {@link
 130.880 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 130.881 +     * Files.readAttributes} method may be used.
 130.882 +     *
 130.883 +     * @return  A <code>long</code> value representing the time the file was
 130.884 +     *          last modified, measured in milliseconds since the epoch
 130.885 +     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
 130.886 +     *          file does not exist or if an I/O error occurs
 130.887 +     *
 130.888 +     * @throws  SecurityException
 130.889 +     *          If a security manager exists and its <code>{@link
 130.890 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.891 +     *          method denies read access to the file
 130.892 +     */
 130.893 +    public long lastModified() {
 130.894 +        throw new SecurityException();
 130.895 +    }
 130.896 +
 130.897 +    /**
 130.898 +     * Returns the length of the file denoted by this abstract pathname.
 130.899 +     * The return value is unspecified if this pathname denotes a directory.
 130.900 +     *
 130.901 +     * <p> Where it is required to distinguish an I/O exception from the case
 130.902 +     * that {@code 0L} is returned, or where several attributes of the same file
 130.903 +     * are required at the same time, then the {@link
 130.904 +     * java.nio.file.Files#readAttributes(Path,Class,LinkOption[])
 130.905 +     * Files.readAttributes} method may be used.
 130.906 +     *
 130.907 +     * @return  The length, in bytes, of the file denoted by this abstract
 130.908 +     *          pathname, or <code>0L</code> if the file does not exist.  Some
 130.909 +     *          operating systems may return <code>0L</code> for pathnames
 130.910 +     *          denoting system-dependent entities such as devices or pipes.
 130.911 +     *
 130.912 +     * @throws  SecurityException
 130.913 +     *          If a security manager exists and its <code>{@link
 130.914 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
 130.915 +     *          method denies read access to the file
 130.916 +     */
 130.917 +    public long length() {
 130.918 +        throw new SecurityException();
 130.919 +    }
 130.920 +
 130.921 +
 130.922 +    /* -- File operations -- */
 130.923 +
 130.924 +    /**
 130.925 +     * Atomically creates a new, empty file named by this abstract pathname if
 130.926 +     * and only if a file with this name does not yet exist.  The check for the
 130.927 +     * existence of the file and the creation of the file if it does not exist
 130.928 +     * are a single operation that is atomic with respect to all other
 130.929 +     * filesystem activities that might affect the file.
 130.930 +     * <P>
 130.931 +     * Note: this method should <i>not</i> be used for file-locking, as
 130.932 +     * the resulting protocol cannot be made to work reliably. The
 130.933 +     * {@link java.nio.channels.FileLock FileLock}
 130.934 +     * facility should be used instead.
 130.935 +     *
 130.936 +     * @return  <code>true</code> if the named file does not exist and was
 130.937 +     *          successfully created; <code>false</code> if the named file
 130.938 +     *          already exists
 130.939 +     *
 130.940 +     * @throws  IOException
 130.941 +     *          If an I/O error occurred
 130.942 +     *
 130.943 +     * @throws  SecurityException
 130.944 +     *          If a security manager exists and its <code>{@link
 130.945 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
 130.946 +     *          method denies write access to the file
 130.947 +     *
 130.948 +     * @since 1.2
 130.949 +     */
 130.950 +    public boolean createNewFile() throws IOException {
 130.951 +        throw new SecurityException();
 130.952 +    }
 130.953 +
 130.954 +    /**
 130.955 +     * Deletes the file or directory denoted by this abstract pathname.  If
 130.956 +     * this pathname denotes a directory, then the directory must be empty in
 130.957 +     * order to be deleted.
 130.958 +     *
 130.959 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
 130.960 +     * java.nio.file.Files#delete(Path) delete} method to throw an {@link IOException}
 130.961 +     * when a file cannot be deleted. This is useful for error reporting and to
 130.962 +     * diagnose why a file cannot be deleted.
 130.963 +     *
 130.964 +     * @return  <code>true</code> if and only if the file or directory is
 130.965 +     *          successfully deleted; <code>false</code> otherwise
 130.966 +     *
 130.967 +     * @throws  SecurityException
 130.968 +     *          If a security manager exists and its <code>{@link
 130.969 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
 130.970 +     *          delete access to the file
 130.971 +     */
 130.972 +    public boolean delete() {
 130.973 +        throw new SecurityException();
 130.974 +    }
 130.975 +
 130.976 +    /**
 130.977 +     * Requests that the file or directory denoted by this abstract
 130.978 +     * pathname be deleted when the virtual machine terminates.
 130.979 +     * Files (or directories) are deleted in the reverse order that
 130.980 +     * they are registered. Invoking this method to delete a file or
 130.981 +     * directory that is already registered for deletion has no effect.
 130.982 +     * Deletion will be attempted only for normal termination of the
 130.983 +     * virtual machine, as defined by the Java Language Specification.
 130.984 +     *
 130.985 +     * <p> Once deletion has been requested, it is not possible to cancel the
 130.986 +     * request.  This method should therefore be used with care.
 130.987 +     *
 130.988 +     * <P>
 130.989 +     * Note: this method should <i>not</i> be used for file-locking, as
 130.990 +     * the resulting protocol cannot be made to work reliably. The
 130.991 +     * {@link java.nio.channels.FileLock FileLock}
 130.992 +     * facility should be used instead.
 130.993 +     *
 130.994 +     * @throws  SecurityException
 130.995 +     *          If a security manager exists and its <code>{@link
 130.996 +     *          java.lang.SecurityManager#checkDelete}</code> method denies
 130.997 +     *          delete access to the file
 130.998 +     *
 130.999 +     * @see #delete
130.1000 +     *
130.1001 +     * @since 1.2
130.1002 +     */
130.1003 +    public void deleteOnExit() {
130.1004 +        throw new SecurityException();
130.1005 +    }
130.1006 +
130.1007 +    /**
130.1008 +     * Returns an array of strings naming the files and directories in the
130.1009 +     * directory denoted by this abstract pathname.
130.1010 +     *
130.1011 +     * <p> If this abstract pathname does not denote a directory, then this
130.1012 +     * method returns {@code null}.  Otherwise an array of strings is
130.1013 +     * returned, one for each file or directory in the directory.  Names
130.1014 +     * denoting the directory itself and the directory's parent directory are
130.1015 +     * not included in the result.  Each string is a file name rather than a
130.1016 +     * complete path.
130.1017 +     *
130.1018 +     * <p> There is no guarantee that the name strings in the resulting array
130.1019 +     * will appear in any specific order; they are not, in particular,
130.1020 +     * guaranteed to appear in alphabetical order.
130.1021 +     *
130.1022 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
130.1023 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method to
130.1024 +     * open a directory and iterate over the names of the files in the directory.
130.1025 +     * This may use less resources when working with very large directories, and
130.1026 +     * may be more responsive when working with remote directories.
130.1027 +     *
130.1028 +     * @return  An array of strings naming the files and directories in the
130.1029 +     *          directory denoted by this abstract pathname.  The array will be
130.1030 +     *          empty if the directory is empty.  Returns {@code null} if
130.1031 +     *          this abstract pathname does not denote a directory, or if an
130.1032 +     *          I/O error occurs.
130.1033 +     *
130.1034 +     * @throws  SecurityException
130.1035 +     *          If a security manager exists and its {@link
130.1036 +     *          SecurityManager#checkRead(String)} method denies read access to
130.1037 +     *          the directory
130.1038 +     */
130.1039 +    public String[] list() {
130.1040 +        throw new SecurityException();
130.1041 +    }
130.1042 +
130.1043 +    /**
130.1044 +     * Returns an array of strings naming the files and directories in the
130.1045 +     * directory denoted by this abstract pathname that satisfy the specified
130.1046 +     * filter.  The behavior of this method is the same as that of the
130.1047 +     * {@link #list()} method, except that the strings in the returned array
130.1048 +     * must satisfy the filter.  If the given {@code filter} is {@code null}
130.1049 +     * then all names are accepted.  Otherwise, a name satisfies the filter if
130.1050 +     * and only if the value {@code true} results when the {@link
130.1051 +     * FilenameFilter#accept FilenameFilter.accept(File,&nbsp;String)} method
130.1052 +     * of the filter is invoked on this abstract pathname and the name of a
130.1053 +     * file or directory in the directory that it denotes.
130.1054 +     *
130.1055 +     * @param  filter
130.1056 +     *         A filename filter
130.1057 +     *
130.1058 +     * @return  An array of strings naming the files and directories in the
130.1059 +     *          directory denoted by this abstract pathname that were accepted
130.1060 +     *          by the given {@code filter}.  The array will be empty if the
130.1061 +     *          directory is empty or if no names were accepted by the filter.
130.1062 +     *          Returns {@code null} if this abstract pathname does not denote
130.1063 +     *          a directory, or if an I/O error occurs.
130.1064 +     *
130.1065 +     * @throws  SecurityException
130.1066 +     *          If a security manager exists and its {@link
130.1067 +     *          SecurityManager#checkRead(String)} method denies read access to
130.1068 +     *          the directory
130.1069 +     *
130.1070 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
130.1071 +     */
130.1072 +    public String[] list(FilenameFilter filter) {
130.1073 +        throw new SecurityException();
130.1074 +    }
130.1075 +
130.1076 +    /**
130.1077 +     * Returns an array of abstract pathnames denoting the files in the
130.1078 +     * directory denoted by this abstract pathname.
130.1079 +     *
130.1080 +     * <p> If this abstract pathname does not denote a directory, then this
130.1081 +     * method returns {@code null}.  Otherwise an array of {@code File} objects
130.1082 +     * is returned, one for each file or directory in the directory.  Pathnames
130.1083 +     * denoting the directory itself and the directory's parent directory are
130.1084 +     * not included in the result.  Each resulting abstract pathname is
130.1085 +     * constructed from this abstract pathname using the {@link #File(File,
130.1086 +     * String) File(File,&nbsp;String)} constructor.  Therefore if this
130.1087 +     * pathname is absolute then each resulting pathname is absolute; if this
130.1088 +     * pathname is relative then each resulting pathname will be relative to
130.1089 +     * the same directory.
130.1090 +     *
130.1091 +     * <p> There is no guarantee that the name strings in the resulting array
130.1092 +     * will appear in any specific order; they are not, in particular,
130.1093 +     * guaranteed to appear in alphabetical order.
130.1094 +     *
130.1095 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
130.1096 +     * java.nio.file.Files#newDirectoryStream(Path) newDirectoryStream} method
130.1097 +     * to open a directory and iterate over the names of the files in the
130.1098 +     * directory. This may use less resources when working with very large
130.1099 +     * directories.
130.1100 +     *
130.1101 +     * @return  An array of abstract pathnames denoting the files and
130.1102 +     *          directories in the directory denoted by this abstract pathname.
130.1103 +     *          The array will be empty if the directory is empty.  Returns
130.1104 +     *          {@code null} if this abstract pathname does not denote a
130.1105 +     *          directory, or if an I/O error occurs.
130.1106 +     *
130.1107 +     * @throws  SecurityException
130.1108 +     *          If a security manager exists and its {@link
130.1109 +     *          SecurityManager#checkRead(String)} method denies read access to
130.1110 +     *          the directory
130.1111 +     *
130.1112 +     * @since  1.2
130.1113 +     */
130.1114 +    public File[] listFiles() {
130.1115 +        throw new SecurityException();
130.1116 +    }
130.1117 +
130.1118 +    /**
130.1119 +     * Returns an array of abstract pathnames denoting the files and
130.1120 +     * directories in the directory denoted by this abstract pathname that
130.1121 +     * satisfy the specified filter.  The behavior of this method is the same
130.1122 +     * as that of the {@link #listFiles()} method, except that the pathnames in
130.1123 +     * the returned array must satisfy the filter.  If the given {@code filter}
130.1124 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
130.1125 +     * satisfies the filter if and only if the value {@code true} results when
130.1126 +     * the {@link FilenameFilter#accept
130.1127 +     * FilenameFilter.accept(File,&nbsp;String)} method of the filter is
130.1128 +     * invoked on this abstract pathname and the name of a file or directory in
130.1129 +     * the directory that it denotes.
130.1130 +     *
130.1131 +     * @param  filter
130.1132 +     *         A filename filter
130.1133 +     *
130.1134 +     * @return  An array of abstract pathnames denoting the files and
130.1135 +     *          directories in the directory denoted by this abstract pathname.
130.1136 +     *          The array will be empty if the directory is empty.  Returns
130.1137 +     *          {@code null} if this abstract pathname does not denote a
130.1138 +     *          directory, or if an I/O error occurs.
130.1139 +     *
130.1140 +     * @throws  SecurityException
130.1141 +     *          If a security manager exists and its {@link
130.1142 +     *          SecurityManager#checkRead(String)} method denies read access to
130.1143 +     *          the directory
130.1144 +     *
130.1145 +     * @since  1.2
130.1146 +     * @see java.nio.file.Files#newDirectoryStream(Path,String)
130.1147 +     */
130.1148 +    public File[] listFiles(FilenameFilter filter) {
130.1149 +        throw new SecurityException();
130.1150 +    }
130.1151 +
130.1152 +    /**
130.1153 +     * Returns an array of abstract pathnames denoting the files and
130.1154 +     * directories in the directory denoted by this abstract pathname that
130.1155 +     * satisfy the specified filter.  The behavior of this method is the same
130.1156 +     * as that of the {@link #listFiles()} method, except that the pathnames in
130.1157 +     * the returned array must satisfy the filter.  If the given {@code filter}
130.1158 +     * is {@code null} then all pathnames are accepted.  Otherwise, a pathname
130.1159 +     * satisfies the filter if and only if the value {@code true} results when
130.1160 +     * the {@link FileFilter#accept FileFilter.accept(File)} method of the
130.1161 +     * filter is invoked on the pathname.
130.1162 +     *
130.1163 +     * @param  filter
130.1164 +     *         A file filter
130.1165 +     *
130.1166 +     * @return  An array of abstract pathnames denoting the files and
130.1167 +     *          directories in the directory denoted by this abstract pathname.
130.1168 +     *          The array will be empty if the directory is empty.  Returns
130.1169 +     *          {@code null} if this abstract pathname does not denote a
130.1170 +     *          directory, or if an I/O error occurs.
130.1171 +     *
130.1172 +     * @throws  SecurityException
130.1173 +     *          If a security manager exists and its {@link
130.1174 +     *          SecurityManager#checkRead(String)} method denies read access to
130.1175 +     *          the directory
130.1176 +     *
130.1177 +     * @since  1.2
130.1178 +     * @see java.nio.file.Files#newDirectoryStream(Path,java.nio.file.DirectoryStream.Filter)
130.1179 +     */
130.1180 +    public File[] listFiles(FileFilter filter) {
130.1181 +        throw new SecurityException();
130.1182 +    }
130.1183 +
130.1184 +    /**
130.1185 +     * Creates the directory named by this abstract pathname.
130.1186 +     *
130.1187 +     * @return  <code>true</code> if and only if the directory was
130.1188 +     *          created; <code>false</code> otherwise
130.1189 +     *
130.1190 +     * @throws  SecurityException
130.1191 +     *          If a security manager exists and its <code>{@link
130.1192 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1193 +     *          method does not permit the named directory to be created
130.1194 +     */
130.1195 +    public boolean mkdir() {
130.1196 +        throw new SecurityException();
130.1197 +    }
130.1198 +
130.1199 +    /**
130.1200 +     * Creates the directory named by this abstract pathname, including any
130.1201 +     * necessary but nonexistent parent directories.  Note that if this
130.1202 +     * operation fails it may have succeeded in creating some of the necessary
130.1203 +     * parent directories.
130.1204 +     *
130.1205 +     * @return  <code>true</code> if and only if the directory was created,
130.1206 +     *          along with all necessary parent directories; <code>false</code>
130.1207 +     *          otherwise
130.1208 +     *
130.1209 +     * @throws  SecurityException
130.1210 +     *          If a security manager exists and its <code>{@link
130.1211 +     *          java.lang.SecurityManager#checkRead(java.lang.String)}</code>
130.1212 +     *          method does not permit verification of the existence of the
130.1213 +     *          named directory and all necessary parent directories; or if
130.1214 +     *          the <code>{@link
130.1215 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1216 +     *          method does not permit the named directory and all necessary
130.1217 +     *          parent directories to be created
130.1218 +     */
130.1219 +    public boolean mkdirs() {
130.1220 +        throw new SecurityException();
130.1221 +    }
130.1222 +
130.1223 +    /**
130.1224 +     * Renames the file denoted by this abstract pathname.
130.1225 +     *
130.1226 +     * <p> Many aspects of the behavior of this method are inherently
130.1227 +     * platform-dependent: The rename operation might not be able to move a
130.1228 +     * file from one filesystem to another, it might not be atomic, and it
130.1229 +     * might not succeed if a file with the destination abstract pathname
130.1230 +     * already exists.  The return value should always be checked to make sure
130.1231 +     * that the rename operation was successful.
130.1232 +     *
130.1233 +     * <p> Note that the {@link java.nio.file.Files} class defines the {@link
130.1234 +     * java.nio.file.Files#move move} method to move or rename a file in a
130.1235 +     * platform independent manner.
130.1236 +     *
130.1237 +     * @param  dest  The new abstract pathname for the named file
130.1238 +     *
130.1239 +     * @return  <code>true</code> if and only if the renaming succeeded;
130.1240 +     *          <code>false</code> otherwise
130.1241 +     *
130.1242 +     * @throws  SecurityException
130.1243 +     *          If a security manager exists and its <code>{@link
130.1244 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1245 +     *          method denies write access to either the old or new pathnames
130.1246 +     *
130.1247 +     * @throws  NullPointerException
130.1248 +     *          If parameter <code>dest</code> is <code>null</code>
130.1249 +     */
130.1250 +    public boolean renameTo(File dest) {
130.1251 +        throw new SecurityException();
130.1252 +    }
130.1253 +
130.1254 +    /**
130.1255 +     * Sets the last-modified time of the file or directory named by this
130.1256 +     * abstract pathname.
130.1257 +     *
130.1258 +     * <p> All platforms support file-modification times to the nearest second,
130.1259 +     * but some provide more precision.  The argument will be truncated to fit
130.1260 +     * the supported precision.  If the operation succeeds and no intervening
130.1261 +     * operations on the file take place, then the next invocation of the
130.1262 +     * <code>{@link #lastModified}</code> method will return the (possibly
130.1263 +     * truncated) <code>time</code> argument that was passed to this method.
130.1264 +     *
130.1265 +     * @param  time  The new last-modified time, measured in milliseconds since
130.1266 +     *               the epoch (00:00:00 GMT, January 1, 1970)
130.1267 +     *
130.1268 +     * @return <code>true</code> if and only if the operation succeeded;
130.1269 +     *          <code>false</code> otherwise
130.1270 +     *
130.1271 +     * @throws  IllegalArgumentException  If the argument is negative
130.1272 +     *
130.1273 +     * @throws  SecurityException
130.1274 +     *          If a security manager exists and its <code>{@link
130.1275 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1276 +     *          method denies write access to the named file
130.1277 +     *
130.1278 +     * @since 1.2
130.1279 +     */
130.1280 +    public boolean setLastModified(long time) {
130.1281 +        throw new SecurityException();
130.1282 +    }
130.1283 +
130.1284 +    /**
130.1285 +     * Marks the file or directory named by this abstract pathname so that
130.1286 +     * only read operations are allowed.  After invoking this method the file
130.1287 +     * or directory is guaranteed not to change until it is either deleted or
130.1288 +     * marked to allow write access.  Whether or not a read-only file or
130.1289 +     * directory may be deleted depends upon the underlying system.
130.1290 +     *
130.1291 +     * @return <code>true</code> if and only if the operation succeeded;
130.1292 +     *          <code>false</code> otherwise
130.1293 +     *
130.1294 +     * @throws  SecurityException
130.1295 +     *          If a security manager exists and its <code>{@link
130.1296 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1297 +     *          method denies write access to the named file
130.1298 +     *
130.1299 +     * @since 1.2
130.1300 +     */
130.1301 +    public boolean setReadOnly() {
130.1302 +        throw new SecurityException();
130.1303 +    }
130.1304 +
130.1305 +    /**
130.1306 +     * Sets the owner's or everybody's write permission for this abstract
130.1307 +     * pathname.
130.1308 +     *
130.1309 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
130.1310 +     * file attributes including file permissions. This may be used when finer
130.1311 +     * manipulation of file permissions is required.
130.1312 +     *
130.1313 +     * @param   writable
130.1314 +     *          If <code>true</code>, sets the access permission to allow write
130.1315 +     *          operations; if <code>false</code> to disallow write operations
130.1316 +     *
130.1317 +     * @param   ownerOnly
130.1318 +     *          If <code>true</code>, the write permission applies only to the
130.1319 +     *          owner's write permission; otherwise, it applies to everybody.  If
130.1320 +     *          the underlying file system can not distinguish the owner's write
130.1321 +     *          permission from that of others, then the permission will apply to
130.1322 +     *          everybody, regardless of this value.
130.1323 +     *
130.1324 +     * @return  <code>true</code> if and only if the operation succeeded. The
130.1325 +     *          operation will fail if the user does not have permission to change
130.1326 +     *          the access permissions of this abstract pathname.
130.1327 +     *
130.1328 +     * @throws  SecurityException
130.1329 +     *          If a security manager exists and its <code>{@link
130.1330 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1331 +     *          method denies write access to the named file
130.1332 +     *
130.1333 +     * @since 1.6
130.1334 +     */
130.1335 +    public boolean setWritable(boolean writable, boolean ownerOnly) {
130.1336 +        throw new SecurityException();
130.1337 +    }
130.1338 +
130.1339 +    /**
130.1340 +     * A convenience method to set the owner's write permission for this abstract
130.1341 +     * pathname.
130.1342 +     *
130.1343 +     * <p> An invocation of this method of the form <tt>file.setWritable(arg)</tt>
130.1344 +     * behaves in exactly the same way as the invocation
130.1345 +     *
130.1346 +     * <pre>
130.1347 +     *     file.setWritable(arg, true) </pre>
130.1348 +     *
130.1349 +     * @param   writable
130.1350 +     *          If <code>true</code>, sets the access permission to allow write
130.1351 +     *          operations; if <code>false</code> to disallow write operations
130.1352 +     *
130.1353 +     * @return  <code>true</code> if and only if the operation succeeded.  The
130.1354 +     *          operation will fail if the user does not have permission to
130.1355 +     *          change the access permissions of this abstract pathname.
130.1356 +     *
130.1357 +     * @throws  SecurityException
130.1358 +     *          If a security manager exists and its <code>{@link
130.1359 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1360 +     *          method denies write access to the file
130.1361 +     *
130.1362 +     * @since 1.6
130.1363 +     */
130.1364 +    public boolean setWritable(boolean writable) {
130.1365 +        return setWritable(writable, true);
130.1366 +    }
130.1367 +
130.1368 +    /**
130.1369 +     * Sets the owner's or everybody's read permission for this abstract
130.1370 +     * pathname.
130.1371 +     *
130.1372 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
130.1373 +     * file attributes including file permissions. This may be used when finer
130.1374 +     * manipulation of file permissions is required.
130.1375 +     *
130.1376 +     * @param   readable
130.1377 +     *          If <code>true</code>, sets the access permission to allow read
130.1378 +     *          operations; if <code>false</code> to disallow read operations
130.1379 +     *
130.1380 +     * @param   ownerOnly
130.1381 +     *          If <code>true</code>, the read permission applies only to the
130.1382 +     *          owner's read permission; otherwise, it applies to everybody.  If
130.1383 +     *          the underlying file system can not distinguish the owner's read
130.1384 +     *          permission from that of others, then the permission will apply to
130.1385 +     *          everybody, regardless of this value.
130.1386 +     *
130.1387 +     * @return  <code>true</code> if and only if the operation succeeded.  The
130.1388 +     *          operation will fail if the user does not have permission to
130.1389 +     *          change the access permissions of this abstract pathname.  If
130.1390 +     *          <code>readable</code> is <code>false</code> and the underlying
130.1391 +     *          file system does not implement a read permission, then the
130.1392 +     *          operation will fail.
130.1393 +     *
130.1394 +     * @throws  SecurityException
130.1395 +     *          If a security manager exists and its <code>{@link
130.1396 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1397 +     *          method denies write access to the file
130.1398 +     *
130.1399 +     * @since 1.6
130.1400 +     */
130.1401 +    public boolean setReadable(boolean readable, boolean ownerOnly) {
130.1402 +        throw new SecurityException();
130.1403 +    }
130.1404 +
130.1405 +    /**
130.1406 +     * A convenience method to set the owner's read permission for this abstract
130.1407 +     * pathname.
130.1408 +     *
130.1409 +     * <p>An invocation of this method of the form <tt>file.setReadable(arg)</tt>
130.1410 +     * behaves in exactly the same way as the invocation
130.1411 +     *
130.1412 +     * <pre>
130.1413 +     *     file.setReadable(arg, true) </pre>
130.1414 +     *
130.1415 +     * @param  readable
130.1416 +     *          If <code>true</code>, sets the access permission to allow read
130.1417 +     *          operations; if <code>false</code> to disallow read operations
130.1418 +     *
130.1419 +     * @return  <code>true</code> if and only if the operation succeeded.  The
130.1420 +     *          operation will fail if the user does not have permission to
130.1421 +     *          change the access permissions of this abstract pathname.  If
130.1422 +     *          <code>readable</code> is <code>false</code> and the underlying
130.1423 +     *          file system does not implement a read permission, then the
130.1424 +     *          operation will fail.
130.1425 +     *
130.1426 +     * @throws  SecurityException
130.1427 +     *          If a security manager exists and its <code>{@link
130.1428 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1429 +     *          method denies write access to the file
130.1430 +     *
130.1431 +     * @since 1.6
130.1432 +     */
130.1433 +    public boolean setReadable(boolean readable) {
130.1434 +        return setReadable(readable, true);
130.1435 +    }
130.1436 +
130.1437 +    /**
130.1438 +     * Sets the owner's or everybody's execute permission for this abstract
130.1439 +     * pathname.
130.1440 +     *
130.1441 +     * <p> The {@link java.nio.file.Files} class defines methods that operate on
130.1442 +     * file attributes including file permissions. This may be used when finer
130.1443 +     * manipulation of file permissions is required.
130.1444 +     *
130.1445 +     * @param   executable
130.1446 +     *          If <code>true</code>, sets the access permission to allow execute
130.1447 +     *          operations; if <code>false</code> to disallow execute operations
130.1448 +     *
130.1449 +     * @param   ownerOnly
130.1450 +     *          If <code>true</code>, the execute permission applies only to the
130.1451 +     *          owner's execute permission; otherwise, it applies to everybody.
130.1452 +     *          If the underlying file system can not distinguish the owner's
130.1453 +     *          execute permission from that of others, then the permission will
130.1454 +     *          apply to everybody, regardless of this value.
130.1455 +     *
130.1456 +     * @return  <code>true</code> if and only if the operation succeeded.  The
130.1457 +     *          operation will fail if the user does not have permission to
130.1458 +     *          change the access permissions of this abstract pathname.  If
130.1459 +     *          <code>executable</code> is <code>false</code> and the underlying
130.1460 +     *          file system does not implement an execute permission, then the
130.1461 +     *          operation will fail.
130.1462 +     *
130.1463 +     * @throws  SecurityException
130.1464 +     *          If a security manager exists and its <code>{@link
130.1465 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1466 +     *          method denies write access to the file
130.1467 +     *
130.1468 +     * @since 1.6
130.1469 +     */
130.1470 +    public boolean setExecutable(boolean executable, boolean ownerOnly) {
130.1471 +        throw new SecurityException();
130.1472 +    }
130.1473 +
130.1474 +    /**
130.1475 +     * A convenience method to set the owner's execute permission for this abstract
130.1476 +     * pathname.
130.1477 +     *
130.1478 +     * <p>An invocation of this method of the form <tt>file.setExcutable(arg)</tt>
130.1479 +     * behaves in exactly the same way as the invocation
130.1480 +     *
130.1481 +     * <pre>
130.1482 +     *     file.setExecutable(arg, true) </pre>
130.1483 +     *
130.1484 +     * @param   executable
130.1485 +     *          If <code>true</code>, sets the access permission to allow execute
130.1486 +     *          operations; if <code>false</code> to disallow execute operations
130.1487 +     *
130.1488 +     * @return   <code>true</code> if and only if the operation succeeded.  The
130.1489 +     *           operation will fail if the user does not have permission to
130.1490 +     *           change the access permissions of this abstract pathname.  If
130.1491 +     *           <code>executable</code> is <code>false</code> and the underlying
130.1492 +     *           file system does not implement an excute permission, then the
130.1493 +     *           operation will fail.
130.1494 +     *
130.1495 +     * @throws  SecurityException
130.1496 +     *          If a security manager exists and its <code>{@link
130.1497 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1498 +     *          method denies write access to the file
130.1499 +     *
130.1500 +     * @since 1.6
130.1501 +     */
130.1502 +    public boolean setExecutable(boolean executable) {
130.1503 +        return setExecutable(executable, true);
130.1504 +    }
130.1505 +
130.1506 +    /**
130.1507 +     * Tests whether the application can execute the file denoted by this
130.1508 +     * abstract pathname.
130.1509 +     *
130.1510 +     * @return  <code>true</code> if and only if the abstract pathname exists
130.1511 +     *          <em>and</em> the application is allowed to execute the file
130.1512 +     *
130.1513 +     * @throws  SecurityException
130.1514 +     *          If a security manager exists and its <code>{@link
130.1515 +     *          java.lang.SecurityManager#checkExec(java.lang.String)}</code>
130.1516 +     *          method denies execute access to the file
130.1517 +     *
130.1518 +     * @since 1.6
130.1519 +     */
130.1520 +    public boolean canExecute() {
130.1521 +        throw new SecurityException();
130.1522 +    }
130.1523 +
130.1524 +
130.1525 +    /* -- Filesystem interface -- */
130.1526 +
130.1527 +    /**
130.1528 +     * List the available filesystem roots.
130.1529 +     *
130.1530 +     * <p> A particular Java platform may support zero or more
130.1531 +     * hierarchically-organized file systems.  Each file system has a
130.1532 +     * {@code root} directory from which all other files in that file system
130.1533 +     * can be reached.  Windows platforms, for example, have a root directory
130.1534 +     * for each active drive; UNIX platforms have a single root directory,
130.1535 +     * namely {@code "/"}.  The set of available filesystem roots is affected
130.1536 +     * by various system-level operations such as the insertion or ejection of
130.1537 +     * removable media and the disconnecting or unmounting of physical or
130.1538 +     * virtual disk drives.
130.1539 +     *
130.1540 +     * <p> This method returns an array of {@code File} objects that denote the
130.1541 +     * root directories of the available filesystem roots.  It is guaranteed
130.1542 +     * that the canonical pathname of any file physically present on the local
130.1543 +     * machine will begin with one of the roots returned by this method.
130.1544 +     *
130.1545 +     * <p> The canonical pathname of a file that resides on some other machine
130.1546 +     * and is accessed via a remote-filesystem protocol such as SMB or NFS may
130.1547 +     * or may not begin with one of the roots returned by this method.  If the
130.1548 +     * pathname of a remote file is syntactically indistinguishable from the
130.1549 +     * pathname of a local file then it will begin with one of the roots
130.1550 +     * returned by this method.  Thus, for example, {@code File} objects
130.1551 +     * denoting the root directories of the mapped network drives of a Windows
130.1552 +     * platform will be returned by this method, while {@code File} objects
130.1553 +     * containing UNC pathnames will not be returned by this method.
130.1554 +     *
130.1555 +     * <p> Unlike most methods in this class, this method does not throw
130.1556 +     * security exceptions.  If a security manager exists and its {@link
130.1557 +     * SecurityManager#checkRead(String)} method denies read access to a
130.1558 +     * particular root directory, then that directory will not appear in the
130.1559 +     * result.
130.1560 +     *
130.1561 +     * @return  An array of {@code File} objects denoting the available
130.1562 +     *          filesystem roots, or {@code null} if the set of roots could not
130.1563 +     *          be determined.  The array will be empty if there are no
130.1564 +     *          filesystem roots.
130.1565 +     *
130.1566 +     * @since  1.2
130.1567 +     * @see java.nio.file.FileStore
130.1568 +     */
130.1569 +    public static File[] listRoots() {
130.1570 +        throw new SecurityException();
130.1571 +    }
130.1572 +
130.1573 +
130.1574 +    /* -- Disk usage -- */
130.1575 +
130.1576 +    /**
130.1577 +     * Returns the size of the partition <a href="#partName">named</a> by this
130.1578 +     * abstract pathname.
130.1579 +     *
130.1580 +     * @return  The size, in bytes, of the partition or <tt>0L</tt> if this
130.1581 +     *          abstract pathname does not name a partition
130.1582 +     *
130.1583 +     * @throws  SecurityException
130.1584 +     *          If a security manager has been installed and it denies
130.1585 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
130.1586 +     *          or its {@link SecurityManager#checkRead(String)} method denies
130.1587 +     *          read access to the file named by this abstract pathname
130.1588 +     *
130.1589 +     * @since  1.6
130.1590 +     */
130.1591 +    public long getTotalSpace() {
130.1592 +        throw new SecurityException();
130.1593 +    }
130.1594 +
130.1595 +    /**
130.1596 +     * Returns the number of unallocated bytes in the partition <a
130.1597 +     * href="#partName">named</a> by this abstract path name.
130.1598 +     *
130.1599 +     * <p> The returned number of unallocated bytes is a hint, but not
130.1600 +     * a guarantee, that it is possible to use most or any of these
130.1601 +     * bytes.  The number of unallocated bytes is most likely to be
130.1602 +     * accurate immediately after this call.  It is likely to be made
130.1603 +     * inaccurate by any external I/O operations including those made
130.1604 +     * on the system outside of this virtual machine.  This method
130.1605 +     * makes no guarantee that write operations to this file system
130.1606 +     * will succeed.
130.1607 +     *
130.1608 +     * @return  The number of unallocated bytes on the partition <tt>0L</tt>
130.1609 +     *          if the abstract pathname does not name a partition.  This
130.1610 +     *          value will be less than or equal to the total file system size
130.1611 +     *          returned by {@link #getTotalSpace}.
130.1612 +     *
130.1613 +     * @throws  SecurityException
130.1614 +     *          If a security manager has been installed and it denies
130.1615 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
130.1616 +     *          or its {@link SecurityManager#checkRead(String)} method denies
130.1617 +     *          read access to the file named by this abstract pathname
130.1618 +     *
130.1619 +     * @since  1.6
130.1620 +     */
130.1621 +    public long getFreeSpace() {
130.1622 +        throw new SecurityException();
130.1623 +    }
130.1624 +
130.1625 +    /**
130.1626 +     * Returns the number of bytes available to this virtual machine on the
130.1627 +     * partition <a href="#partName">named</a> by this abstract pathname.  When
130.1628 +     * possible, this method checks for write permissions and other operating
130.1629 +     * system restrictions and will therefore usually provide a more accurate
130.1630 +     * estimate of how much new data can actually be written than {@link
130.1631 +     * #getFreeSpace}.
130.1632 +     *
130.1633 +     * <p> The returned number of available bytes is a hint, but not a
130.1634 +     * guarantee, that it is possible to use most or any of these bytes.  The
130.1635 +     * number of unallocated bytes is most likely to be accurate immediately
130.1636 +     * after this call.  It is likely to be made inaccurate by any external
130.1637 +     * I/O operations including those made on the system outside of this
130.1638 +     * virtual machine.  This method makes no guarantee that write operations
130.1639 +     * to this file system will succeed.
130.1640 +     *
130.1641 +     * @return  The number of available bytes on the partition or <tt>0L</tt>
130.1642 +     *          if the abstract pathname does not name a partition.  On
130.1643 +     *          systems where this information is not available, this method
130.1644 +     *          will be equivalent to a call to {@link #getFreeSpace}.
130.1645 +     *
130.1646 +     * @throws  SecurityException
130.1647 +     *          If a security manager has been installed and it denies
130.1648 +     *          {@link RuntimePermission}<tt>("getFileSystemAttributes")</tt>
130.1649 +     *          or its {@link SecurityManager#checkRead(String)} method denies
130.1650 +     *          read access to the file named by this abstract pathname
130.1651 +     *
130.1652 +     * @since  1.6
130.1653 +     */
130.1654 +    public long getUsableSpace() {
130.1655 +        throw new SecurityException();
130.1656 +    }
130.1657 +
130.1658 +    /* -- Temporary files -- */
130.1659 +
130.1660 +
130.1661 +    /**
130.1662 +     * <p> Creates a new empty file in the specified directory, using the
130.1663 +     * given prefix and suffix strings to generate its name.  If this method
130.1664 +     * returns successfully then it is guaranteed that:
130.1665 +     *
130.1666 +     * <ol>
130.1667 +     * <li> The file denoted by the returned abstract pathname did not exist
130.1668 +     *      before this method was invoked, and
130.1669 +     * <li> Neither this method nor any of its variants will return the same
130.1670 +     *      abstract pathname again in the current invocation of the virtual
130.1671 +     *      machine.
130.1672 +     * </ol>
130.1673 +     *
130.1674 +     * This method provides only part of a temporary-file facility.  To arrange
130.1675 +     * for a file created by this method to be deleted automatically, use the
130.1676 +     * <code>{@link #deleteOnExit}</code> method.
130.1677 +     *
130.1678 +     * <p> The <code>prefix</code> argument must be at least three characters
130.1679 +     * long.  It is recommended that the prefix be a short, meaningful string
130.1680 +     * such as <code>"hjb"</code> or <code>"mail"</code>.  The
130.1681 +     * <code>suffix</code> argument may be <code>null</code>, in which case the
130.1682 +     * suffix <code>".tmp"</code> will be used.
130.1683 +     *
130.1684 +     * <p> To create the new file, the prefix and the suffix may first be
130.1685 +     * adjusted to fit the limitations of the underlying platform.  If the
130.1686 +     * prefix is too long then it will be truncated, but its first three
130.1687 +     * characters will always be preserved.  If the suffix is too long then it
130.1688 +     * too will be truncated, but if it begins with a period character
130.1689 +     * (<code>'.'</code>) then the period and the first three characters
130.1690 +     * following it will always be preserved.  Once these adjustments have been
130.1691 +     * made the name of the new file will be generated by concatenating the
130.1692 +     * prefix, five or more internally-generated characters, and the suffix.
130.1693 +     *
130.1694 +     * <p> If the <code>directory</code> argument is <code>null</code> then the
130.1695 +     * system-dependent default temporary-file directory will be used.  The
130.1696 +     * default temporary-file directory is specified by the system property
130.1697 +     * <code>java.io.tmpdir</code>.  On UNIX systems the default value of this
130.1698 +     * property is typically <code>"/tmp"</code> or <code>"/var/tmp"</code>; on
130.1699 +     * Microsoft Windows systems it is typically <code>"C:\\WINNT\\TEMP"</code>.  A different
130.1700 +     * value may be given to this system property when the Java virtual machine
130.1701 +     * is invoked, but programmatic changes to this property are not guaranteed
130.1702 +     * to have any effect upon the temporary directory used by this method.
130.1703 +     *
130.1704 +     * @param  prefix     The prefix string to be used in generating the file's
130.1705 +     *                    name; must be at least three characters long
130.1706 +     *
130.1707 +     * @param  suffix     The suffix string to be used in generating the file's
130.1708 +     *                    name; may be <code>null</code>, in which case the
130.1709 +     *                    suffix <code>".tmp"</code> will be used
130.1710 +     *
130.1711 +     * @param  directory  The directory in which the file is to be created, or
130.1712 +     *                    <code>null</code> if the default temporary-file
130.1713 +     *                    directory is to be used
130.1714 +     *
130.1715 +     * @return  An abstract pathname denoting a newly-created empty file
130.1716 +     *
130.1717 +     * @throws  IllegalArgumentException
130.1718 +     *          If the <code>prefix</code> argument contains fewer than three
130.1719 +     *          characters
130.1720 +     *
130.1721 +     * @throws  IOException  If a file could not be created
130.1722 +     *
130.1723 +     * @throws  SecurityException
130.1724 +     *          If a security manager exists and its <code>{@link
130.1725 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1726 +     *          method does not allow a file to be created
130.1727 +     *
130.1728 +     * @since 1.2
130.1729 +     */
130.1730 +    public static File createTempFile(String prefix, String suffix,
130.1731 +                                      File directory)
130.1732 +        throws IOException
130.1733 +    {
130.1734 +        throw new SecurityException();
130.1735 +    }
130.1736 +
130.1737 +    /**
130.1738 +     * Creates an empty file in the default temporary-file directory, using
130.1739 +     * the given prefix and suffix to generate its name. Invoking this method
130.1740 +     * is equivalent to invoking <code>{@link #createTempFile(java.lang.String,
130.1741 +     * java.lang.String, java.io.File)
130.1742 +     * createTempFile(prefix,&nbsp;suffix,&nbsp;null)}</code>.
130.1743 +     *
130.1744 +     * <p> The {@link
130.1745 +     * java.nio.file.Files#createTempFile(String,String,java.nio.file.attribute.FileAttribute[])
130.1746 +     * Files.createTempFile} method provides an alternative method to create an
130.1747 +     * empty file in the temporary-file directory. Files created by that method
130.1748 +     * may have more restrictive access permissions to files created by this
130.1749 +     * method and so may be more suited to security-sensitive applications.
130.1750 +     *
130.1751 +     * @param  prefix     The prefix string to be used in generating the file's
130.1752 +     *                    name; must be at least three characters long
130.1753 +     *
130.1754 +     * @param  suffix     The suffix string to be used in generating the file's
130.1755 +     *                    name; may be <code>null</code>, in which case the
130.1756 +     *                    suffix <code>".tmp"</code> will be used
130.1757 +     *
130.1758 +     * @return  An abstract pathname denoting a newly-created empty file
130.1759 +     *
130.1760 +     * @throws  IllegalArgumentException
130.1761 +     *          If the <code>prefix</code> argument contains fewer than three
130.1762 +     *          characters
130.1763 +     *
130.1764 +     * @throws  IOException  If a file could not be created
130.1765 +     *
130.1766 +     * @throws  SecurityException
130.1767 +     *          If a security manager exists and its <code>{@link
130.1768 +     *          java.lang.SecurityManager#checkWrite(java.lang.String)}</code>
130.1769 +     *          method does not allow a file to be created
130.1770 +     *
130.1771 +     * @since 1.2
130.1772 +     * @see java.nio.file.Files#createTempDirectory(String,FileAttribute[])
130.1773 +     */
130.1774 +    public static File createTempFile(String prefix, String suffix)
130.1775 +        throws IOException
130.1776 +    {
130.1777 +        return createTempFile(prefix, suffix, null);
130.1778 +    }
130.1779 +
130.1780 +    /* -- Basic infrastructure -- */
130.1781 +
130.1782 +    /**
130.1783 +     * Compares two abstract pathnames lexicographically.  The ordering
130.1784 +     * defined by this method depends upon the underlying system.  On UNIX
130.1785 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
130.1786 +     * systems it is not.
130.1787 +     *
130.1788 +     * @param   pathname  The abstract pathname to be compared to this abstract
130.1789 +     *                    pathname
130.1790 +     *
130.1791 +     * @return  Zero if the argument is equal to this abstract pathname, a
130.1792 +     *          value less than zero if this abstract pathname is
130.1793 +     *          lexicographically less than the argument, or a value greater
130.1794 +     *          than zero if this abstract pathname is lexicographically
130.1795 +     *          greater than the argument
130.1796 +     *
130.1797 +     * @since   1.2
130.1798 +     */
130.1799 +    public int compareTo(File pathname) {
130.1800 +        return fs.compare(this, pathname);
130.1801 +    }
130.1802 +
130.1803 +    /**
130.1804 +     * Tests this abstract pathname for equality with the given object.
130.1805 +     * Returns <code>true</code> if and only if the argument is not
130.1806 +     * <code>null</code> and is an abstract pathname that denotes the same file
130.1807 +     * or directory as this abstract pathname.  Whether or not two abstract
130.1808 +     * pathnames are equal depends upon the underlying system.  On UNIX
130.1809 +     * systems, alphabetic case is significant in comparing pathnames; on Microsoft Windows
130.1810 +     * systems it is not.
130.1811 +     *
130.1812 +     * @param   obj   The object to be compared with this abstract pathname
130.1813 +     *
130.1814 +     * @return  <code>true</code> if and only if the objects are the same;
130.1815 +     *          <code>false</code> otherwise
130.1816 +     */
130.1817 +    public boolean equals(Object obj) {
130.1818 +        if ((obj != null) && (obj instanceof File)) {
130.1819 +            return compareTo((File)obj) == 0;
130.1820 +        }
130.1821 +        return false;
130.1822 +    }
130.1823 +
130.1824 +    /**
130.1825 +     * Computes a hash code for this abstract pathname.  Because equality of
130.1826 +     * abstract pathnames is inherently system-dependent, so is the computation
130.1827 +     * of their hash codes.  On UNIX systems, the hash code of an abstract
130.1828 +     * pathname is equal to the exclusive <em>or</em> of the hash code
130.1829 +     * of its pathname string and the decimal value
130.1830 +     * <code>1234321</code>.  On Microsoft Windows systems, the hash
130.1831 +     * code is equal to the exclusive <em>or</em> of the hash code of
130.1832 +     * its pathname string converted to lower case and the decimal
130.1833 +     * value <code>1234321</code>.  Locale is not taken into account on
130.1834 +     * lowercasing the pathname string.
130.1835 +     *
130.1836 +     * @return  A hash code for this abstract pathname
130.1837 +     */
130.1838 +    public int hashCode() {
130.1839 +        return fs.hashCode(this);
130.1840 +    }
130.1841 +
130.1842 +    /**
130.1843 +     * Returns the pathname string of this abstract pathname.  This is just the
130.1844 +     * string returned by the <code>{@link #getPath}</code> method.
130.1845 +     *
130.1846 +     * @return  The string form of this abstract pathname
130.1847 +     */
130.1848 +    public String toString() {
130.1849 +        return getPath();
130.1850 +    }
130.1851 +
130.1852 +    /**
130.1853 +     * WriteObject is called to save this filename.
130.1854 +     * The separator character is saved also so it can be replaced
130.1855 +     * in case the path is reconstituted on a different host type.
130.1856 +     * <p>
130.1857 +     * @serialData  Default fields followed by separator character.
130.1858 +     */
130.1859 +    private synchronized void writeObject(java.io.ObjectOutputStream s)
130.1860 +        throws IOException
130.1861 +    {
130.1862 +        s.defaultWriteObject();
130.1863 +        s.writeChar(this.separatorChar); // Add the separator character
130.1864 +    }
130.1865 +
130.1866 +    /**
130.1867 +     * readObject is called to restore this filename.
130.1868 +     * The original separator character is read.  If it is different
130.1869 +     * than the separator character on this system, then the old separator
130.1870 +     * is replaced by the local separator.
130.1871 +     */
130.1872 +    private synchronized void readObject(java.io.ObjectInputStream s)
130.1873 +         throws IOException, ClassNotFoundException
130.1874 +    {
130.1875 +        ObjectInputStream.GetField fields = s.readFields();
130.1876 +        String pathField = (String)fields.get("path", null);
130.1877 +        char sep = s.readChar(); // read the previous separator char
130.1878 +        if (sep != separatorChar)
130.1879 +            pathField = pathField.replace(sep, separatorChar);
130.1880 +        this.path = fs.normalize(pathField);
130.1881 +        this.prefixLength = fs.prefixLength(this.path);
130.1882 +    }
130.1883 +
130.1884 +    /** use serialVersionUID from JDK 1.0.2 for interoperability */
130.1885 +    private static final long serialVersionUID = 301077366599181567L;
130.1886 +
130.1887 +    // -- Integration with java.nio.file --
130.1888 +/*
130.1889 +    private volatile transient Path filePath;
130.1890 +
130.1891 +    /**
130.1892 +     * Returns a {@link Path java.nio.file.Path} object constructed from the
130.1893 +     * this abstract path. The resulting {@code Path} is associated with the
130.1894 +     * {@link java.nio.file.FileSystems#getDefault default-filesystem}.
130.1895 +     *
130.1896 +     * <p> The first invocation of this method works as if invoking it were
130.1897 +     * equivalent to evaluating the expression:
130.1898 +     * <blockquote><pre>
130.1899 +     * {@link java.nio.file.FileSystems#getDefault FileSystems.getDefault}().{@link
130.1900 +     * java.nio.file.FileSystem#getPath getPath}(this.{@link #getPath getPath}());
130.1901 +     * </pre></blockquote>
130.1902 +     * Subsequent invocations of this method return the same {@code Path}.
130.1903 +     *
130.1904 +     * <p> If this abstract pathname is the empty abstract pathname then this
130.1905 +     * method returns a {@code Path} that may be used to access the current
130.1906 +     * user directory.
130.1907 +     *
130.1908 +     * @return  a {@code Path} constructed from this abstract path
130.1909 +     *
130.1910 +     * @throws  java.nio.file.InvalidPathException
130.1911 +     *          if a {@code Path} object cannot be constructed from the abstract
130.1912 +     *          path (see {@link java.nio.file.FileSystem#getPath FileSystem.getPath})
130.1913 +     *
130.1914 +     * @since   1.7
130.1915 +     * @see Path#toFile
130.1916 +     */
130.1917 +//    public Path toPath() {
130.1918 +//        Path result = filePath;
130.1919 +//        if (result == null) {
130.1920 +//            synchronized (this) {
130.1921 +//                result = filePath;
130.1922 +//                if (result == null) {
130.1923 +//                    result = FileSystems.getDefault().getPath(path);
130.1924 +//                    filePath = result;
130.1925 +//                }
130.1926 +//            }
130.1927 +//        }
130.1928 +//        return result;
130.1929 +//    }
130.1930 +}
   131.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   131.2 +++ b/rt/emul/compact/src/main/java/java/io/FileFilter.java	Mon Oct 07 14:20:58 2013 +0200
   131.3 @@ -0,0 +1,50 @@
   131.4 +/*
   131.5 + * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved.
   131.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   131.7 + *
   131.8 + * This code is free software; you can redistribute it and/or modify it
   131.9 + * under the terms of the GNU General Public License version 2 only, as
  131.10 + * published by the Free Software Foundation.  Oracle designates this
  131.11 + * particular file as subject to the "Classpath" exception as provided
  131.12 + * by Oracle in the LICENSE file that accompanied this code.
  131.13 + *
  131.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  131.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  131.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  131.17 + * version 2 for more details (a copy is included in the LICENSE file that
  131.18 + * accompanied this code).
  131.19 + *
  131.20 + * You should have received a copy of the GNU General Public License version
  131.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  131.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  131.23 + *
  131.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  131.25 + * or visit www.oracle.com if you need additional information or have any
  131.26 + * questions.
  131.27 + */
  131.28 +
  131.29 +package java.io;
  131.30 +
  131.31 +
  131.32 +/**
  131.33 + * A filter for abstract pathnames.
  131.34 + *
  131.35 + * <p> Instances of this interface may be passed to the <code>{@link
  131.36 + * File#listFiles(java.io.FileFilter) listFiles(FileFilter)}</code> method
  131.37 + * of the <code>{@link java.io.File}</code> class.
  131.38 + *
  131.39 + * @since 1.2
  131.40 + */
  131.41 +public interface FileFilter {
  131.42 +
  131.43 +    /**
  131.44 +     * Tests whether or not the specified abstract pathname should be
  131.45 +     * included in a pathname list.
  131.46 +     *
  131.47 +     * @param  pathname  The abstract pathname to be tested
  131.48 +     * @return  <code>true</code> if and only if <code>pathname</code>
  131.49 +     *          should be included
  131.50 +     */
  131.51 +    boolean accept(File pathname);
  131.52 +
  131.53 +}
   132.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   132.2 +++ b/rt/emul/compact/src/main/java/java/io/FileNotFoundException.java	Mon Oct 07 14:20:58 2013 +0200
   132.3 @@ -0,0 +1,82 @@
   132.4 +/*
   132.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
   132.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   132.7 + *
   132.8 + * This code is free software; you can redistribute it and/or modify it
   132.9 + * under the terms of the GNU General Public License version 2 only, as
  132.10 + * published by the Free Software Foundation.  Oracle designates this
  132.11 + * particular file as subject to the "Classpath" exception as provided
  132.12 + * by Oracle in the LICENSE file that accompanied this code.
  132.13 + *
  132.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  132.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  132.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  132.17 + * version 2 for more details (a copy is included in the LICENSE file that
  132.18 + * accompanied this code).
  132.19 + *
  132.20 + * You should have received a copy of the GNU General Public License version
  132.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  132.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  132.23 + *
  132.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  132.25 + * or visit www.oracle.com if you need additional information or have any
  132.26 + * questions.
  132.27 + */
  132.28 +
  132.29 +package java.io;
  132.30 +
  132.31 +
  132.32 +/**
  132.33 + * Signals that an attempt to open the file denoted by a specified pathname
  132.34 + * has failed.
  132.35 + *
  132.36 + * <p> This exception will be thrown by the {@link FileInputStream}, {@link
  132.37 + * FileOutputStream}, and {@link RandomAccessFile} constructors when a file
  132.38 + * with the specified pathname does not exist.  It will also be thrown by these
  132.39 + * constructors if the file does exist but for some reason is inaccessible, for
  132.40 + * example when an attempt is made to open a read-only file for writing.
  132.41 + *
  132.42 + * @author  unascribed
  132.43 + * @since   JDK1.0
  132.44 + */
  132.45 +
  132.46 +public class FileNotFoundException extends IOException {
  132.47 +    private static final long serialVersionUID = -897856973823710492L;
  132.48 +
  132.49 +    /**
  132.50 +     * Constructs a <code>FileNotFoundException</code> with
  132.51 +     * <code>null</code> as its error detail message.
  132.52 +     */
  132.53 +    public FileNotFoundException() {
  132.54 +        super();
  132.55 +    }
  132.56 +
  132.57 +    /**
  132.58 +     * Constructs a <code>FileNotFoundException</code> with the
  132.59 +     * specified detail message. The string <code>s</code> can be
  132.60 +     * retrieved later by the
  132.61 +     * <code>{@link java.lang.Throwable#getMessage}</code>
  132.62 +     * method of class <code>java.lang.Throwable</code>.
  132.63 +     *
  132.64 +     * @param   s   the detail message.
  132.65 +     */
  132.66 +    public FileNotFoundException(String s) {
  132.67 +        super(s);
  132.68 +    }
  132.69 +
  132.70 +    /**
  132.71 +     * Constructs a <code>FileNotFoundException</code> with a detail message
  132.72 +     * consisting of the given pathname string followed by the given reason
  132.73 +     * string.  If the <code>reason</code> argument is <code>null</code> then
  132.74 +     * it will be omitted.  This private constructor is invoked only by native
  132.75 +     * I/O methods.
  132.76 +     *
  132.77 +     * @since 1.2
  132.78 +     */
  132.79 +    private FileNotFoundException(String path, String reason) {
  132.80 +        super(path + ((reason == null)
  132.81 +                      ? ""
  132.82 +                      : " (" + reason + ")"));
  132.83 +    }
  132.84 +
  132.85 +}
   133.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   133.2 +++ b/rt/emul/compact/src/main/java/java/io/FilenameFilter.java	Mon Oct 07 14:20:58 2013 +0200
   133.3 @@ -0,0 +1,53 @@
   133.4 +/*
   133.5 + * Copyright (c) 1994, 1998, Oracle and/or its affiliates. All rights reserved.
   133.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   133.7 + *
   133.8 + * This code is free software; you can redistribute it and/or modify it
   133.9 + * under the terms of the GNU General Public License version 2 only, as
  133.10 + * published by the Free Software Foundation.  Oracle designates this
  133.11 + * particular file as subject to the "Classpath" exception as provided
  133.12 + * by Oracle in the LICENSE file that accompanied this code.
  133.13 + *
  133.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  133.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  133.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  133.17 + * version 2 for more details (a copy is included in the LICENSE file that
  133.18 + * accompanied this code).
  133.19 + *
  133.20 + * You should have received a copy of the GNU General Public License version
  133.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  133.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  133.23 + *
  133.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  133.25 + * or visit www.oracle.com if you need additional information or have any
  133.26 + * questions.
  133.27 + */
  133.28 +
  133.29 +package java.io;
  133.30 +
  133.31 +/**
  133.32 + * Instances of classes that implement this interface are used to
  133.33 + * filter filenames. These instances are used to filter directory
  133.34 + * listings in the <code>list</code> method of class
  133.35 + * <code>File</code>, and by the Abstract Window Toolkit's file
  133.36 + * dialog component.
  133.37 + *
  133.38 + * @author  Arthur van Hoff
  133.39 + * @author  Jonathan Payne
  133.40 + * @see     java.awt.FileDialog#setFilenameFilter(java.io.FilenameFilter)
  133.41 + * @see     java.io.File
  133.42 + * @see     java.io.File#list(java.io.FilenameFilter)
  133.43 + * @since   JDK1.0
  133.44 + */
  133.45 +public
  133.46 +interface FilenameFilter {
  133.47 +    /**
  133.48 +     * Tests if a specified file should be included in a file list.
  133.49 +     *
  133.50 +     * @param   dir    the directory in which the file was found.
  133.51 +     * @param   name   the name of the file.
  133.52 +     * @return  <code>true</code> if and only if the name should be
  133.53 +     * included in the file list; <code>false</code> otherwise.
  133.54 +     */
  133.55 +    boolean accept(File dir, String name);
  133.56 +}
   134.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   134.2 +++ b/rt/emul/compact/src/main/java/java/io/InterruptedIOException.java	Mon Oct 07 14:20:58 2013 +0200
   134.3 @@ -0,0 +1,74 @@
   134.4 +/*
   134.5 + * Copyright (c) 1995, 2008, Oracle and/or its affiliates. All rights reserved.
   134.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   134.7 + *
   134.8 + * This code is free software; you can redistribute it and/or modify it
   134.9 + * under the terms of the GNU General Public License version 2 only, as
  134.10 + * published by the Free Software Foundation.  Oracle designates this
  134.11 + * particular file as subject to the "Classpath" exception as provided
  134.12 + * by Oracle in the LICENSE file that accompanied this code.
  134.13 + *
  134.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  134.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  134.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  134.17 + * version 2 for more details (a copy is included in the LICENSE file that
  134.18 + * accompanied this code).
  134.19 + *
  134.20 + * You should have received a copy of the GNU General Public License version
  134.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  134.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  134.23 + *
  134.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  134.25 + * or visit www.oracle.com if you need additional information or have any
  134.26 + * questions.
  134.27 + */
  134.28 +
  134.29 +package java.io;
  134.30 +
  134.31 +/**
  134.32 + * Signals that an I/O operation has been interrupted. An
  134.33 + * <code>InterruptedIOException</code> is thrown to indicate that an
  134.34 + * input or output transfer has been terminated because the thread
  134.35 + * performing it was interrupted. The field {@link #bytesTransferred}
  134.36 + * indicates how many bytes were successfully transferred before
  134.37 + * the interruption occurred.
  134.38 + *
  134.39 + * @author  unascribed
  134.40 + * @see     java.io.InputStream
  134.41 + * @see     java.io.OutputStream
  134.42 + * @see     java.lang.Thread#interrupt()
  134.43 + * @since   JDK1.0
  134.44 + */
  134.45 +public
  134.46 +class InterruptedIOException extends IOException {
  134.47 +    private static final long serialVersionUID = 4020568460727500567L;
  134.48 +
  134.49 +    /**
  134.50 +     * Constructs an <code>InterruptedIOException</code> with
  134.51 +     * <code>null</code> as its error detail message.
  134.52 +     */
  134.53 +    public InterruptedIOException() {
  134.54 +        super();
  134.55 +    }
  134.56 +
  134.57 +    /**
  134.58 +     * Constructs an <code>InterruptedIOException</code> with the
  134.59 +     * specified detail message. The string <code>s</code> can be
  134.60 +     * retrieved later by the
  134.61 +     * <code>{@link java.lang.Throwable#getMessage}</code>
  134.62 +     * method of class <code>java.lang.Throwable</code>.
  134.63 +     *
  134.64 +     * @param   s   the detail message.
  134.65 +     */
  134.66 +    public InterruptedIOException(String s) {
  134.67 +        super(s);
  134.68 +    }
  134.69 +
  134.70 +    /**
  134.71 +     * Reports how many bytes had been transferred as part of the I/O
  134.72 +     * operation before it was interrupted.
  134.73 +     *
  134.74 +     * @serial
  134.75 +     */
  134.76 +    public int bytesTransferred = 0;
  134.77 +}
   135.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   135.2 +++ b/rt/emul/compact/src/main/java/java/io/OutputStreamWriter.java	Mon Oct 07 14:20:58 2013 +0200
   135.3 @@ -0,0 +1,242 @@
   135.4 +/*
   135.5 + * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
   135.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   135.7 + *
   135.8 + * This code is free software; you can redistribute it and/or modify it
   135.9 + * under the terms of the GNU General Public License version 2 only, as
  135.10 + * published by the Free Software Foundation.  Oracle designates this
  135.11 + * particular file as subject to the "Classpath" exception as provided
  135.12 + * by Oracle in the LICENSE file that accompanied this code.
  135.13 + *
  135.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  135.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  135.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  135.17 + * version 2 for more details (a copy is included in the LICENSE file that
  135.18 + * accompanied this code).
  135.19 + *
  135.20 + * You should have received a copy of the GNU General Public License version
  135.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  135.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  135.23 + *
  135.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  135.25 + * or visit www.oracle.com if you need additional information or have any
  135.26 + * questions.
  135.27 + */
  135.28 +
  135.29 +package java.io;
  135.30 +
  135.31 +/**
  135.32 + * An OutputStreamWriter is a bridge from character streams to byte streams:
  135.33 + * Characters written to it are encoded into bytes using a specified {@link
  135.34 + * java.nio.charset.Charset <code>charset</code>}.  The charset that it uses
  135.35 + * may be specified by name or may be given explicitly, or the platform's
  135.36 + * default charset may be accepted.
  135.37 + *
  135.38 + * <p> Each invocation of a write() method causes the encoding converter to be
  135.39 + * invoked on the given character(s).  The resulting bytes are accumulated in a
  135.40 + * buffer before being written to the underlying output stream.  The size of
  135.41 + * this buffer may be specified, but by default it is large enough for most
  135.42 + * purposes.  Note that the characters passed to the write() methods are not
  135.43 + * buffered.
  135.44 + *
  135.45 + * <p> For top efficiency, consider wrapping an OutputStreamWriter within a
  135.46 + * BufferedWriter so as to avoid frequent converter invocations.  For example:
  135.47 + *
  135.48 + * <pre>
  135.49 + * Writer out
  135.50 + *   = new BufferedWriter(new OutputStreamWriter(System.out));
  135.51 + * </pre>
  135.52 + *
  135.53 + * <p> A <i>surrogate pair</i> is a character represented by a sequence of two
  135.54 + * <tt>char</tt> values: A <i>high</i> surrogate in the range '&#92;uD800' to
  135.55 + * '&#92;uDBFF' followed by a <i>low</i> surrogate in the range '&#92;uDC00' to
  135.56 + * '&#92;uDFFF'.
  135.57 + *
  135.58 + * <p> A <i>malformed surrogate element</i> is a high surrogate that is not
  135.59 + * followed by a low surrogate or a low surrogate that is not preceded by a
  135.60 + * high surrogate.
  135.61 + *
  135.62 + * <p> This class always replaces malformed surrogate elements and unmappable
  135.63 + * character sequences with the charset's default <i>substitution sequence</i>.
  135.64 + * The {@linkplain java.nio.charset.CharsetEncoder} class should be used when more
  135.65 + * control over the encoding process is required.
  135.66 + *
  135.67 + * @see BufferedWriter
  135.68 + * @see OutputStream
  135.69 + * @see java.nio.charset.Charset
  135.70 + *
  135.71 + * @author      Mark Reinhold
  135.72 + * @since       JDK1.1
  135.73 + */
  135.74 +
  135.75 +public class OutputStreamWriter extends Writer {
  135.76 +    
  135.77 +    /**
  135.78 +     * Creates an OutputStreamWriter that uses the named charset.
  135.79 +     *
  135.80 +     * @param  out
  135.81 +     *         An OutputStream
  135.82 +     *
  135.83 +     * @param  charsetName
  135.84 +     *         The name of a supported
  135.85 +     *         {@link java.nio.charset.Charset </code>charset<code>}
  135.86 +     *
  135.87 +     * @exception  UnsupportedEncodingException
  135.88 +     *             If the named encoding is not supported
  135.89 +     */
  135.90 +    public OutputStreamWriter(OutputStream out, String charsetName)
  135.91 +        throws UnsupportedEncodingException
  135.92 +    {
  135.93 +        super(out);
  135.94 +        if (charsetName == null)
  135.95 +            throw new NullPointerException("charsetName");
  135.96 +        if (!charsetName.toUpperCase().equals("UTF-8")) {
  135.97 +            throw new UnsupportedEncodingException(charsetName);
  135.98 +        }
  135.99 +    }
 135.100 +
 135.101 +    /**
 135.102 +     * Creates an OutputStreamWriter that uses the default character encoding.
 135.103 +     *
 135.104 +     * @param  out  An OutputStream
 135.105 +     */
 135.106 +    public OutputStreamWriter(OutputStream out) {
 135.107 +        super(out);
 135.108 +    }
 135.109 +
 135.110 +    /**
 135.111 +     * Creates an OutputStreamWriter that uses the given charset. </p>
 135.112 +     *
 135.113 +     * @param  out
 135.114 +     *         An OutputStream
 135.115 +     *
 135.116 +     * @param  cs
 135.117 +     *         A charset
 135.118 +     *
 135.119 +     * @since 1.4
 135.120 +     * @spec JSR-51
 135.121 +     */
 135.122 +//    public OutputStreamWriter(OutputStream out, Charset cs) {
 135.123 +//        super(out);
 135.124 +//        if (cs == null)
 135.125 +//            throw new NullPointerException("charset");
 135.126 +//        se = StreamEncoder.forOutputStreamWriter(out, this, cs);
 135.127 +//    }
 135.128 +
 135.129 +    /**
 135.130 +     * Creates an OutputStreamWriter that uses the given charset encoder.  </p>
 135.131 +     *
 135.132 +     * @param  out
 135.133 +     *         An OutputStream
 135.134 +     *
 135.135 +     * @param  enc
 135.136 +     *         A charset encoder
 135.137 +     *
 135.138 +     * @since 1.4
 135.139 +     * @spec JSR-51
 135.140 +     */
 135.141 +//    public OutputStreamWriter(OutputStream out, CharsetEncoder enc) {
 135.142 +//        super(out);
 135.143 +//        if (enc == null)
 135.144 +//            throw new NullPointerException("charset encoder");
 135.145 +//        se = StreamEncoder.forOutputStreamWriter(out, this, enc);
 135.146 +//    }
 135.147 +
 135.148 +    /**
 135.149 +     * Returns the name of the character encoding being used by this stream.
 135.150 +     *
 135.151 +     * <p> If the encoding has an historical name then that name is returned;
 135.152 +     * otherwise the encoding's canonical name is returned.
 135.153 +     *
 135.154 +     * <p> If this instance was created with the {@link
 135.155 +     * #OutputStreamWriter(OutputStream, String)} constructor then the returned
 135.156 +     * name, being unique for the encoding, may differ from the name passed to
 135.157 +     * the constructor.  This method may return <tt>null</tt> if the stream has
 135.158 +     * been closed. </p>
 135.159 +     *
 135.160 +     * @return The historical name of this encoding, or possibly
 135.161 +     *         <code>null</code> if the stream has been closed
 135.162 +     *
 135.163 +     * @see java.nio.charset.Charset
 135.164 +     *
 135.165 +     * @revised 1.4
 135.166 +     * @spec JSR-51
 135.167 +     */
 135.168 +    public String getEncoding() {
 135.169 +        return "UTF-8";
 135.170 +    }
 135.171 +
 135.172 +    /**
 135.173 +     * Flushes the output buffer to the underlying byte stream, without flushing
 135.174 +     * the byte stream itself.  This method is non-private only so that it may
 135.175 +     * be invoked by PrintStream.
 135.176 +     */
 135.177 +    void flushBuffer() throws IOException {
 135.178 +        out().flush();
 135.179 +    }
 135.180 +
 135.181 +    /**
 135.182 +     * Writes a single character.
 135.183 +     *
 135.184 +     * @exception  IOException  If an I/O error occurs
 135.185 +     */
 135.186 +    public void write(int c) throws IOException {
 135.187 +        if (c <= 0x7F) {
 135.188 +            out().write(c);
 135.189 +        } else if (c <= 0x7FF) {
 135.190 +            out().write(0xC0 | (c >> 6));
 135.191 +            out().write(0x80 | (c & 0x3F));
 135.192 +        } else {
 135.193 +            out().write(0xE0 | (c >> 12));
 135.194 +            out().write(0x80 | ((c >> 6) & 0x3F));
 135.195 +            out().write(0x80 | (c & 0x3F));
 135.196 +        }
 135.197 +    }
 135.198 +
 135.199 +    /**
 135.200 +     * Writes a portion of an array of characters.
 135.201 +     *
 135.202 +     * @param  cbuf  Buffer of characters
 135.203 +     * @param  off   Offset from which to start writing characters
 135.204 +     * @param  len   Number of characters to write
 135.205 +     *
 135.206 +     * @exception  IOException  If an I/O error occurs
 135.207 +     */
 135.208 +    public void write(char cbuf[], int off, int len) throws IOException {
 135.209 +        while (len-- > 0) {
 135.210 +            write(cbuf[off++]);
 135.211 +        }
 135.212 +    }
 135.213 +
 135.214 +    /**
 135.215 +     * Writes a portion of a string.
 135.216 +     *
 135.217 +     * @param  str  A String
 135.218 +     * @param  off  Offset from which to start writing characters
 135.219 +     * @param  len  Number of characters to write
 135.220 +     *
 135.221 +     * @exception  IOException  If an I/O error occurs
 135.222 +     */
 135.223 +    public void write(String str, int off, int len) throws IOException {
 135.224 +        while (len-- > 0) {
 135.225 +            write(str.charAt(off++));
 135.226 +        }
 135.227 +    }
 135.228 +
 135.229 +    /**
 135.230 +     * Flushes the stream.
 135.231 +     *
 135.232 +     * @exception  IOException  If an I/O error occurs
 135.233 +     */
 135.234 +    public void flush() throws IOException {
 135.235 +        out().flush();
 135.236 +    }
 135.237 +
 135.238 +    public void close() throws IOException {
 135.239 +        out().close();
 135.240 +    }
 135.241 +    
 135.242 +    private OutputStream out() {
 135.243 +        return (OutputStream) lock;
 135.244 +    }
 135.245 +}
   136.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   136.2 +++ b/rt/emul/compact/src/main/java/java/io/PrintStream.java	Mon Oct 07 14:20:58 2013 +0200
   136.3 @@ -0,0 +1,1125 @@
   136.4 +/*
   136.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   136.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   136.7 + *
   136.8 + * This code is free software; you can redistribute it and/or modify it
   136.9 + * under the terms of the GNU General Public License version 2 only, as
  136.10 + * published by the Free Software Foundation.  Oracle designates this
  136.11 + * particular file as subject to the "Classpath" exception as provided
  136.12 + * by Oracle in the LICENSE file that accompanied this code.
  136.13 + *
  136.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  136.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  136.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  136.17 + * version 2 for more details (a copy is included in the LICENSE file that
  136.18 + * accompanied this code).
  136.19 + *
  136.20 + * You should have received a copy of the GNU General Public License version
  136.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  136.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  136.23 + *
  136.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  136.25 + * or visit www.oracle.com if you need additional information or have any
  136.26 + * questions.
  136.27 + */
  136.28 +
  136.29 +package java.io;
  136.30 +
  136.31 +import java.util.Arrays;
  136.32 +
  136.33 +
  136.34 +/**
  136.35 + * A <code>PrintStream</code> adds functionality to another output stream,
  136.36 + * namely the ability to print representations of various data values
  136.37 + * conveniently.  Two other features are provided as well.  Unlike other output
  136.38 + * streams, a <code>PrintStream</code> never throws an
  136.39 + * <code>IOException</code>; instead, exceptional situations merely set an
  136.40 + * internal flag that can be tested via the <code>checkError</code> method.
  136.41 + * Optionally, a <code>PrintStream</code> can be created so as to flush
  136.42 + * automatically; this means that the <code>flush</code> method is
  136.43 + * automatically invoked after a byte array is written, one of the
  136.44 + * <code>println</code> methods is invoked, or a newline character or byte
  136.45 + * (<code>'\n'</code>) is written.
  136.46 + *
  136.47 + * <p> All characters printed by a <code>PrintStream</code> are converted into
  136.48 + * bytes using the platform's default character encoding.  The <code>{@link
  136.49 + * PrintWriter}</code> class should be used in situations that require writing
  136.50 + * characters rather than bytes.
  136.51 + *
  136.52 + * @author     Frank Yellin
  136.53 + * @author     Mark Reinhold
  136.54 + * @since      JDK1.0
  136.55 + */
  136.56 +
  136.57 +public class PrintStream extends FilterOutputStream
  136.58 +    implements Appendable, Closeable
  136.59 +{
  136.60 +
  136.61 +    private final boolean autoFlush;
  136.62 +    private boolean trouble = false;
  136.63 +    private Formatter formatter;
  136.64 +
  136.65 +    /**
  136.66 +     * Track both the text- and character-output streams, so that their buffers
  136.67 +     * can be flushed without flushing the entire stream.
  136.68 +     */
  136.69 +    private BufferedWriter textOut;
  136.70 +    private OutputStreamWriter charOut;
  136.71 +
  136.72 +    /**
  136.73 +     * requireNonNull is explicitly declared here so as not to create an extra
  136.74 +     * dependency on java.util.Objects.requireNonNull. PrintStream is loaded
  136.75 +     * early during system initialization.
  136.76 +     */
  136.77 +    private static <T> T requireNonNull(T obj, String message) {
  136.78 +        if (obj == null)
  136.79 +            throw new NullPointerException(message);
  136.80 +        return obj;
  136.81 +    }
  136.82 +
  136.83 +    /* Private constructors */
  136.84 +    private PrintStream(boolean autoFlush, OutputStream out) {
  136.85 +        super(out);
  136.86 +        this.autoFlush = autoFlush;
  136.87 +        this.charOut = new OutputStreamWriter(this);
  136.88 +        this.textOut = new BufferedWriter(charOut);
  136.89 +    }
  136.90 +    
  136.91 +    static final class Formatter {
  136.92 +    }
  136.93 +    
  136.94 +    static final class Charset {
  136.95 +    }
  136.96 +    
  136.97 +    static Charset toCharset(String ch) throws UnsupportedEncodingException {
  136.98 +        if (!"UTF-8".equals(ch)) {
  136.99 +            throw new UnsupportedEncodingException();
 136.100 +        }
 136.101 +        return null;
 136.102 +    }
 136.103 +
 136.104 +    private PrintStream(boolean autoFlush, OutputStream out, Charset charset) {
 136.105 +        super(out);
 136.106 +        this.autoFlush = autoFlush;
 136.107 +        this.charOut = new OutputStreamWriter(this);
 136.108 +        this.textOut = new BufferedWriter(charOut);
 136.109 +    }
 136.110 +
 136.111 +    /* Variant of the private constructor so that the given charset name
 136.112 +     * can be verified before evaluating the OutputStream argument. Used
 136.113 +     * by constructors creating a FileOutputStream that also take a
 136.114 +     * charset name.
 136.115 +     */
 136.116 +    private PrintStream(boolean autoFlush, Charset charset, OutputStream out)
 136.117 +        throws UnsupportedEncodingException
 136.118 +    {
 136.119 +        this(autoFlush, out, charset);
 136.120 +    }
 136.121 +
 136.122 +    /**
 136.123 +     * Creates a new print stream.  This stream will not flush automatically.
 136.124 +     *
 136.125 +     * @param  out        The output stream to which values and objects will be
 136.126 +     *                    printed
 136.127 +     *
 136.128 +     * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream)
 136.129 +     */
 136.130 +    public PrintStream(OutputStream out) {
 136.131 +        this(out, false);
 136.132 +    }
 136.133 +
 136.134 +    /**
 136.135 +     * Creates a new print stream.
 136.136 +     *
 136.137 +     * @param  out        The output stream to which values and objects will be
 136.138 +     *                    printed
 136.139 +     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
 136.140 +     *                    whenever a byte array is written, one of the
 136.141 +     *                    <code>println</code> methods is invoked, or a newline
 136.142 +     *                    character or byte (<code>'\n'</code>) is written
 136.143 +     *
 136.144 +     * @see java.io.PrintWriter#PrintWriter(java.io.OutputStream, boolean)
 136.145 +     */
 136.146 +    public PrintStream(OutputStream out, boolean autoFlush) {
 136.147 +        this(autoFlush, requireNonNull(out, "Null output stream"));
 136.148 +    }
 136.149 +
 136.150 +    /**
 136.151 +     * Creates a new print stream.
 136.152 +     *
 136.153 +     * @param  out        The output stream to which values and objects will be
 136.154 +     *                    printed
 136.155 +     * @param  autoFlush  A boolean; if true, the output buffer will be flushed
 136.156 +     *                    whenever a byte array is written, one of the
 136.157 +     *                    <code>println</code> methods is invoked, or a newline
 136.158 +     *                    character or byte (<code>'\n'</code>) is written
 136.159 +     * @param  encoding   The name of a supported
 136.160 +     *                    <a href="../lang/package-summary.html#charenc">
 136.161 +     *                    character encoding</a>
 136.162 +     *
 136.163 +     * @throws  UnsupportedEncodingException
 136.164 +     *          If the named encoding is not supported
 136.165 +     *
 136.166 +     * @since  1.4
 136.167 +     */
 136.168 +    public PrintStream(OutputStream out, boolean autoFlush, String encoding)
 136.169 +        throws UnsupportedEncodingException
 136.170 +    {
 136.171 +        this(autoFlush,
 136.172 +             requireNonNull(out, "Null output stream"),
 136.173 +             toCharset(encoding));
 136.174 +    }
 136.175 +
 136.176 +    /**
 136.177 +     * Creates a new print stream, without automatic line flushing, with the
 136.178 +     * specified file name.  This convenience constructor creates
 136.179 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 136.180 +     * OutputStreamWriter}, which will encode characters using the
 136.181 +     * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}
 136.182 +     * for this instance of the Java virtual machine.
 136.183 +     *
 136.184 +     * @param  fileName
 136.185 +     *         The name of the file to use as the destination of this print
 136.186 +     *         stream.  If the file exists, then it will be truncated to
 136.187 +     *         zero size; otherwise, a new file will be created.  The output
 136.188 +     *         will be written to the file and is buffered.
 136.189 +     *
 136.190 +     * @throws  FileNotFoundException
 136.191 +     *          If the given file object does not denote an existing, writable
 136.192 +     *          regular file and a new regular file of that name cannot be
 136.193 +     *          created, or if some other error occurs while opening or
 136.194 +     *          creating the file
 136.195 +     *
 136.196 +     * @throws  SecurityException
 136.197 +     *          If a security manager is present and {@link
 136.198 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 136.199 +     *          access to the file
 136.200 +     *
 136.201 +     * @since  1.5
 136.202 +     */
 136.203 +    public PrintStream(String fileName) throws FileNotFoundException {
 136.204 +        super(null);
 136.205 +        throw new FileNotFoundException();
 136.206 +    }
 136.207 +
 136.208 +    /**
 136.209 +     * Creates a new print stream, without automatic line flushing, with the
 136.210 +     * specified file name and charset.  This convenience constructor creates
 136.211 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 136.212 +     * OutputStreamWriter}, which will encode characters using the provided
 136.213 +     * charset.
 136.214 +     *
 136.215 +     * @param  fileName
 136.216 +     *         The name of the file to use as the destination of this print
 136.217 +     *         stream.  If the file exists, then it will be truncated to
 136.218 +     *         zero size; otherwise, a new file will be created.  The output
 136.219 +     *         will be written to the file and is buffered.
 136.220 +     *
 136.221 +     * @param  csn
 136.222 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 136.223 +     *         charset}
 136.224 +     *
 136.225 +     * @throws  FileNotFoundException
 136.226 +     *          If the given file object does not denote an existing, writable
 136.227 +     *          regular file and a new regular file of that name cannot be
 136.228 +     *          created, or if some other error occurs while opening or
 136.229 +     *          creating the file
 136.230 +     *
 136.231 +     * @throws  SecurityException
 136.232 +     *          If a security manager is present and {@link
 136.233 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 136.234 +     *          access to the file
 136.235 +     *
 136.236 +     * @throws  UnsupportedEncodingException
 136.237 +     *          If the named charset is not supported
 136.238 +     *
 136.239 +     * @since  1.5
 136.240 +     */
 136.241 +    public PrintStream(String fileName, String csn)
 136.242 +        throws FileNotFoundException, UnsupportedEncodingException
 136.243 +    {
 136.244 +        super(null);
 136.245 +        throw new FileNotFoundException();
 136.246 +    }
 136.247 +
 136.248 +    /**
 136.249 +     * Creates a new print stream, without automatic line flushing, with the
 136.250 +     * specified file.  This convenience constructor creates the necessary
 136.251 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 136.252 +     * which will encode characters using the {@linkplain
 136.253 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 136.254 +     * instance of the Java virtual machine.
 136.255 +     *
 136.256 +     * @param  file
 136.257 +     *         The file to use as the destination of this print stream.  If the
 136.258 +     *         file exists, then it will be truncated to zero size; otherwise,
 136.259 +     *         a new file will be created.  The output will be written to the
 136.260 +     *         file and is buffered.
 136.261 +     *
 136.262 +     * @throws  FileNotFoundException
 136.263 +     *          If the given file object does not denote an existing, writable
 136.264 +     *          regular file and a new regular file of that name cannot be
 136.265 +     *          created, or if some other error occurs while opening or
 136.266 +     *          creating the file
 136.267 +     *
 136.268 +     * @throws  SecurityException
 136.269 +     *          If a security manager is present and {@link
 136.270 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 136.271 +     *          denies write access to the file
 136.272 +     *
 136.273 +     * @since  1.5
 136.274 +     */
 136.275 +    public PrintStream(File file) throws FileNotFoundException {
 136.276 +        super(null);
 136.277 +        throw new FileNotFoundException();
 136.278 +    }
 136.279 +
 136.280 +    /**
 136.281 +     * Creates a new print stream, without automatic line flushing, with the
 136.282 +     * specified file and charset.  This convenience constructor creates
 136.283 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 136.284 +     * OutputStreamWriter}, which will encode characters using the provided
 136.285 +     * charset.
 136.286 +     *
 136.287 +     * @param  file
 136.288 +     *         The file to use as the destination of this print stream.  If the
 136.289 +     *         file exists, then it will be truncated to zero size; otherwise,
 136.290 +     *         a new file will be created.  The output will be written to the
 136.291 +     *         file and is buffered.
 136.292 +     *
 136.293 +     * @param  csn
 136.294 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 136.295 +     *         charset}
 136.296 +     *
 136.297 +     * @throws  FileNotFoundException
 136.298 +     *          If the given file object does not denote an existing, writable
 136.299 +     *          regular file and a new regular file of that name cannot be
 136.300 +     *          created, or if some other error occurs while opening or
 136.301 +     *          creating the file
 136.302 +     *
 136.303 +     * @throws  SecurityException
 136.304 +     *          If a security manager is presentand {@link
 136.305 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 136.306 +     *          denies write access to the file
 136.307 +     *
 136.308 +     * @throws  UnsupportedEncodingException
 136.309 +     *          If the named charset is not supported
 136.310 +     *
 136.311 +     * @since  1.5
 136.312 +     */
 136.313 +    public PrintStream(File file, String csn)
 136.314 +        throws FileNotFoundException, UnsupportedEncodingException
 136.315 +    {
 136.316 +        super(null);
 136.317 +        throw new FileNotFoundException();
 136.318 +    }
 136.319 +
 136.320 +    /** Check to make sure that the stream has not been closed */
 136.321 +    private void ensureOpen() throws IOException {
 136.322 +        if (out == null)
 136.323 +            throw new IOException("Stream closed");
 136.324 +    }
 136.325 +
 136.326 +    /**
 136.327 +     * Flushes the stream.  This is done by writing any buffered output bytes to
 136.328 +     * the underlying output stream and then flushing that stream.
 136.329 +     *
 136.330 +     * @see        java.io.OutputStream#flush()
 136.331 +     */
 136.332 +    public void flush() {
 136.333 +        synchronized (this) {
 136.334 +            try {
 136.335 +                ensureOpen();
 136.336 +                out.flush();
 136.337 +            }
 136.338 +            catch (IOException x) {
 136.339 +                trouble = true;
 136.340 +            }
 136.341 +        }
 136.342 +    }
 136.343 +
 136.344 +    private boolean closing = false; /* To avoid recursive closing */
 136.345 +
 136.346 +    /**
 136.347 +     * Closes the stream.  This is done by flushing the stream and then closing
 136.348 +     * the underlying output stream.
 136.349 +     *
 136.350 +     * @see        java.io.OutputStream#close()
 136.351 +     */
 136.352 +    public void close() {
 136.353 +        synchronized (this) {
 136.354 +            if (! closing) {
 136.355 +                closing = true;
 136.356 +                try {
 136.357 +                    textOut.close();
 136.358 +                    out.close();
 136.359 +                }
 136.360 +                catch (IOException x) {
 136.361 +                    trouble = true;
 136.362 +                }
 136.363 +                textOut = null;
 136.364 +                charOut = null;
 136.365 +                out = null;
 136.366 +            }
 136.367 +        }
 136.368 +    }
 136.369 +
 136.370 +    /**
 136.371 +     * Flushes the stream and checks its error state. The internal error state
 136.372 +     * is set to <code>true</code> when the underlying output stream throws an
 136.373 +     * <code>IOException</code> other than <code>InterruptedIOException</code>,
 136.374 +     * and when the <code>setError</code> method is invoked.  If an operation
 136.375 +     * on the underlying output stream throws an
 136.376 +     * <code>InterruptedIOException</code>, then the <code>PrintStream</code>
 136.377 +     * converts the exception back into an interrupt by doing:
 136.378 +     * <pre>
 136.379 +     *     Thread.currentThread().interrupt();
 136.380 +     * </pre>
 136.381 +     * or the equivalent.
 136.382 +     *
 136.383 +     * @return <code>true</code> if and only if this stream has encountered an
 136.384 +     *         <code>IOException</code> other than
 136.385 +     *         <code>InterruptedIOException</code>, or the
 136.386 +     *         <code>setError</code> method has been invoked
 136.387 +     */
 136.388 +    public boolean checkError() {
 136.389 +        if (out != null)
 136.390 +            flush();
 136.391 +        if (out instanceof java.io.PrintStream) {
 136.392 +            PrintStream ps = (PrintStream) out;
 136.393 +            return ps.checkError();
 136.394 +        }
 136.395 +        return trouble;
 136.396 +    }
 136.397 +
 136.398 +    /**
 136.399 +     * Sets the error state of the stream to <code>true</code>.
 136.400 +     *
 136.401 +     * <p> This method will cause subsequent invocations of {@link
 136.402 +     * #checkError()} to return <tt>true</tt> until {@link
 136.403 +     * #clearError()} is invoked.
 136.404 +     *
 136.405 +     * @since JDK1.1
 136.406 +     */
 136.407 +    protected void setError() {
 136.408 +        trouble = true;
 136.409 +    }
 136.410 +
 136.411 +    /**
 136.412 +     * Clears the internal error state of this stream.
 136.413 +     *
 136.414 +     * <p> This method will cause subsequent invocations of {@link
 136.415 +     * #checkError()} to return <tt>false</tt> until another write
 136.416 +     * operation fails and invokes {@link #setError()}.
 136.417 +     *
 136.418 +     * @since 1.6
 136.419 +     */
 136.420 +    protected void clearError() {
 136.421 +        trouble = false;
 136.422 +    }
 136.423 +
 136.424 +    /*
 136.425 +     * Exception-catching, synchronized output operations,
 136.426 +     * which also implement the write() methods of OutputStream
 136.427 +     */
 136.428 +
 136.429 +    /**
 136.430 +     * Writes the specified byte to this stream.  If the byte is a newline and
 136.431 +     * automatic flushing is enabled then the <code>flush</code> method will be
 136.432 +     * invoked.
 136.433 +     *
 136.434 +     * <p> Note that the byte is written as given; to write a character that
 136.435 +     * will be translated according to the platform's default character
 136.436 +     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
 136.437 +     * methods.
 136.438 +     *
 136.439 +     * @param  b  The byte to be written
 136.440 +     * @see #print(char)
 136.441 +     * @see #println(char)
 136.442 +     */
 136.443 +    public void write(int b) {
 136.444 +        try {
 136.445 +            synchronized (this) {
 136.446 +                ensureOpen();
 136.447 +                out.write(b);
 136.448 +                if ((b == '\n') && autoFlush)
 136.449 +                    out.flush();
 136.450 +            }
 136.451 +        }
 136.452 +        catch (InterruptedIOException x) {
 136.453 +            Thread.currentThread().interrupt();
 136.454 +        }
 136.455 +        catch (IOException x) {
 136.456 +            trouble = true;
 136.457 +        }
 136.458 +    }
 136.459 +
 136.460 +    /**
 136.461 +     * Writes <code>len</code> bytes from the specified byte array starting at
 136.462 +     * offset <code>off</code> to this stream.  If automatic flushing is
 136.463 +     * enabled then the <code>flush</code> method will be invoked.
 136.464 +     *
 136.465 +     * <p> Note that the bytes will be written as given; to write characters
 136.466 +     * that will be translated according to the platform's default character
 136.467 +     * encoding, use the <code>print(char)</code> or <code>println(char)</code>
 136.468 +     * methods.
 136.469 +     *
 136.470 +     * @param  buf   A byte array
 136.471 +     * @param  off   Offset from which to start taking bytes
 136.472 +     * @param  len   Number of bytes to write
 136.473 +     */
 136.474 +    public void write(byte buf[], int off, int len) {
 136.475 +        try {
 136.476 +            synchronized (this) {
 136.477 +                ensureOpen();
 136.478 +                out.write(buf, off, len);
 136.479 +                if (autoFlush)
 136.480 +                    out.flush();
 136.481 +            }
 136.482 +        }
 136.483 +        catch (InterruptedIOException x) {
 136.484 +            Thread.currentThread().interrupt();
 136.485 +        }
 136.486 +        catch (IOException x) {
 136.487 +            trouble = true;
 136.488 +        }
 136.489 +    }
 136.490 +
 136.491 +    /*
 136.492 +     * The following private methods on the text- and character-output streams
 136.493 +     * always flush the stream buffers, so that writes to the underlying byte
 136.494 +     * stream occur as promptly as with the original PrintStream.
 136.495 +     */
 136.496 +
 136.497 +    private void write(char buf[]) {
 136.498 +        try {
 136.499 +            synchronized (this) {
 136.500 +                ensureOpen();
 136.501 +                textOut.write(buf);
 136.502 +                textOut.flushBuffer();
 136.503 +                charOut.flushBuffer();
 136.504 +                if (autoFlush) {
 136.505 +                    for (int i = 0; i < buf.length; i++)
 136.506 +                        if (buf[i] == '\n')
 136.507 +                            out.flush();
 136.508 +                }
 136.509 +            }
 136.510 +        }
 136.511 +        catch (InterruptedIOException x) {
 136.512 +            Thread.currentThread().interrupt();
 136.513 +        }
 136.514 +        catch (IOException x) {
 136.515 +            trouble = true;
 136.516 +        }
 136.517 +    }
 136.518 +
 136.519 +    private void write(String s) {
 136.520 +        try {
 136.521 +            synchronized (this) {
 136.522 +                ensureOpen();
 136.523 +                textOut.write(s);
 136.524 +                textOut.flushBuffer();
 136.525 +                charOut.flushBuffer();
 136.526 +                if (autoFlush && (s.indexOf('\n') >= 0))
 136.527 +                    out.flush();
 136.528 +            }
 136.529 +        }
 136.530 +        catch (InterruptedIOException x) {
 136.531 +            Thread.currentThread().interrupt();
 136.532 +        }
 136.533 +        catch (IOException x) {
 136.534 +            trouble = true;
 136.535 +        }
 136.536 +    }
 136.537 +
 136.538 +    private void newLine() {
 136.539 +        try {
 136.540 +            synchronized (this) {
 136.541 +                ensureOpen();
 136.542 +                textOut.newLine();
 136.543 +                textOut.flushBuffer();
 136.544 +                charOut.flushBuffer();
 136.545 +                if (autoFlush)
 136.546 +                    out.flush();
 136.547 +            }
 136.548 +        }
 136.549 +        catch (InterruptedIOException x) {
 136.550 +            Thread.currentThread().interrupt();
 136.551 +        }
 136.552 +        catch (IOException x) {
 136.553 +            trouble = true;
 136.554 +        }
 136.555 +    }
 136.556 +
 136.557 +    /* Methods that do not terminate lines */
 136.558 +
 136.559 +    /**
 136.560 +     * Prints a boolean value.  The string produced by <code>{@link
 136.561 +     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
 136.562 +     * according to the platform's default character encoding, and these bytes
 136.563 +     * are written in exactly the manner of the
 136.564 +     * <code>{@link #write(int)}</code> method.
 136.565 +     *
 136.566 +     * @param      b   The <code>boolean</code> to be printed
 136.567 +     */
 136.568 +    public void print(boolean b) {
 136.569 +        write(b ? "true" : "false");
 136.570 +    }
 136.571 +
 136.572 +    /**
 136.573 +     * Prints a character.  The character is translated into one or more bytes
 136.574 +     * according to the platform's default character encoding, and these bytes
 136.575 +     * are written in exactly the manner of the
 136.576 +     * <code>{@link #write(int)}</code> method.
 136.577 +     *
 136.578 +     * @param      c   The <code>char</code> to be printed
 136.579 +     */
 136.580 +    public void print(char c) {
 136.581 +        write(String.valueOf(c));
 136.582 +    }
 136.583 +
 136.584 +    /**
 136.585 +     * Prints an integer.  The string produced by <code>{@link
 136.586 +     * java.lang.String#valueOf(int)}</code> is translated into bytes
 136.587 +     * according to the platform's default character encoding, and these bytes
 136.588 +     * are written in exactly the manner of the
 136.589 +     * <code>{@link #write(int)}</code> method.
 136.590 +     *
 136.591 +     * @param      i   The <code>int</code> to be printed
 136.592 +     * @see        java.lang.Integer#toString(int)
 136.593 +     */
 136.594 +    public void print(int i) {
 136.595 +        write(String.valueOf(i));
 136.596 +    }
 136.597 +
 136.598 +    /**
 136.599 +     * Prints a long integer.  The string produced by <code>{@link
 136.600 +     * java.lang.String#valueOf(long)}</code> is translated into bytes
 136.601 +     * according to the platform's default character encoding, and these bytes
 136.602 +     * are written in exactly the manner of the
 136.603 +     * <code>{@link #write(int)}</code> method.
 136.604 +     *
 136.605 +     * @param      l   The <code>long</code> to be printed
 136.606 +     * @see        java.lang.Long#toString(long)
 136.607 +     */
 136.608 +    public void print(long l) {
 136.609 +        write(String.valueOf(l));
 136.610 +    }
 136.611 +
 136.612 +    /**
 136.613 +     * Prints a floating-point number.  The string produced by <code>{@link
 136.614 +     * java.lang.String#valueOf(float)}</code> is translated into bytes
 136.615 +     * according to the platform's default character encoding, and these bytes
 136.616 +     * are written in exactly the manner of the
 136.617 +     * <code>{@link #write(int)}</code> method.
 136.618 +     *
 136.619 +     * @param      f   The <code>float</code> to be printed
 136.620 +     * @see        java.lang.Float#toString(float)
 136.621 +     */
 136.622 +    public void print(float f) {
 136.623 +        write(String.valueOf(f));
 136.624 +    }
 136.625 +
 136.626 +    /**
 136.627 +     * Prints a double-precision floating-point number.  The string produced by
 136.628 +     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
 136.629 +     * bytes according to the platform's default character encoding, and these
 136.630 +     * bytes are written in exactly the manner of the <code>{@link
 136.631 +     * #write(int)}</code> method.
 136.632 +     *
 136.633 +     * @param      d   The <code>double</code> to be printed
 136.634 +     * @see        java.lang.Double#toString(double)
 136.635 +     */
 136.636 +    public void print(double d) {
 136.637 +        write(String.valueOf(d));
 136.638 +    }
 136.639 +
 136.640 +    /**
 136.641 +     * Prints an array of characters.  The characters are converted into bytes
 136.642 +     * according to the platform's default character encoding, and these bytes
 136.643 +     * are written in exactly the manner of the
 136.644 +     * <code>{@link #write(int)}</code> method.
 136.645 +     *
 136.646 +     * @param      s   The array of chars to be printed
 136.647 +     *
 136.648 +     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
 136.649 +     */
 136.650 +    public void print(char s[]) {
 136.651 +        write(s);
 136.652 +    }
 136.653 +
 136.654 +    /**
 136.655 +     * Prints a string.  If the argument is <code>null</code> then the string
 136.656 +     * <code>"null"</code> is printed.  Otherwise, the string's characters are
 136.657 +     * converted into bytes according to the platform's default character
 136.658 +     * encoding, and these bytes are written in exactly the manner of the
 136.659 +     * <code>{@link #write(int)}</code> method.
 136.660 +     *
 136.661 +     * @param      s   The <code>String</code> to be printed
 136.662 +     */
 136.663 +    public void print(String s) {
 136.664 +        if (s == null) {
 136.665 +            s = "null";
 136.666 +        }
 136.667 +        write(s);
 136.668 +    }
 136.669 +
 136.670 +    /**
 136.671 +     * Prints an object.  The string produced by the <code>{@link
 136.672 +     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
 136.673 +     * according to the platform's default character encoding, and these bytes
 136.674 +     * are written in exactly the manner of the
 136.675 +     * <code>{@link #write(int)}</code> method.
 136.676 +     *
 136.677 +     * @param      obj   The <code>Object</code> to be printed
 136.678 +     * @see        java.lang.Object#toString()
 136.679 +     */
 136.680 +    public void print(Object obj) {
 136.681 +        write(String.valueOf(obj));
 136.682 +    }
 136.683 +
 136.684 +
 136.685 +    /* Methods that do terminate lines */
 136.686 +
 136.687 +    /**
 136.688 +     * Terminates the current line by writing the line separator string.  The
 136.689 +     * line separator string is defined by the system property
 136.690 +     * <code>line.separator</code>, and is not necessarily a single newline
 136.691 +     * character (<code>'\n'</code>).
 136.692 +     */
 136.693 +    public void println() {
 136.694 +        newLine();
 136.695 +    }
 136.696 +
 136.697 +    /**
 136.698 +     * Prints a boolean and then terminate the line.  This method behaves as
 136.699 +     * though it invokes <code>{@link #print(boolean)}</code> and then
 136.700 +     * <code>{@link #println()}</code>.
 136.701 +     *
 136.702 +     * @param x  The <code>boolean</code> to be printed
 136.703 +     */
 136.704 +    public void println(boolean x) {
 136.705 +        synchronized (this) {
 136.706 +            print(x);
 136.707 +            newLine();
 136.708 +        }
 136.709 +    }
 136.710 +
 136.711 +    /**
 136.712 +     * Prints a character and then terminate the line.  This method behaves as
 136.713 +     * though it invokes <code>{@link #print(char)}</code> and then
 136.714 +     * <code>{@link #println()}</code>.
 136.715 +     *
 136.716 +     * @param x  The <code>char</code> to be printed.
 136.717 +     */
 136.718 +    public void println(char x) {
 136.719 +        synchronized (this) {
 136.720 +            print(x);
 136.721 +            newLine();
 136.722 +        }
 136.723 +    }
 136.724 +
 136.725 +    /**
 136.726 +     * Prints an integer and then terminate the line.  This method behaves as
 136.727 +     * though it invokes <code>{@link #print(int)}</code> and then
 136.728 +     * <code>{@link #println()}</code>.
 136.729 +     *
 136.730 +     * @param x  The <code>int</code> to be printed.
 136.731 +     */
 136.732 +    public void println(int x) {
 136.733 +        synchronized (this) {
 136.734 +            print(x);
 136.735 +            newLine();
 136.736 +        }
 136.737 +    }
 136.738 +
 136.739 +    /**
 136.740 +     * Prints a long and then terminate the line.  This method behaves as
 136.741 +     * though it invokes <code>{@link #print(long)}</code> and then
 136.742 +     * <code>{@link #println()}</code>.
 136.743 +     *
 136.744 +     * @param x  a The <code>long</code> to be printed.
 136.745 +     */
 136.746 +    public void println(long x) {
 136.747 +        synchronized (this) {
 136.748 +            print(x);
 136.749 +            newLine();
 136.750 +        }
 136.751 +    }
 136.752 +
 136.753 +    /**
 136.754 +     * Prints a float and then terminate the line.  This method behaves as
 136.755 +     * though it invokes <code>{@link #print(float)}</code> and then
 136.756 +     * <code>{@link #println()}</code>.
 136.757 +     *
 136.758 +     * @param x  The <code>float</code> to be printed.
 136.759 +     */
 136.760 +    public void println(float x) {
 136.761 +        synchronized (this) {
 136.762 +            print(x);
 136.763 +            newLine();
 136.764 +        }
 136.765 +    }
 136.766 +
 136.767 +    /**
 136.768 +     * Prints a double and then terminate the line.  This method behaves as
 136.769 +     * though it invokes <code>{@link #print(double)}</code> and then
 136.770 +     * <code>{@link #println()}</code>.
 136.771 +     *
 136.772 +     * @param x  The <code>double</code> to be printed.
 136.773 +     */
 136.774 +    public void println(double x) {
 136.775 +        synchronized (this) {
 136.776 +            print(x);
 136.777 +            newLine();
 136.778 +        }
 136.779 +    }
 136.780 +
 136.781 +    /**
 136.782 +     * Prints an array of characters and then terminate the line.  This method
 136.783 +     * behaves as though it invokes <code>{@link #print(char[])}</code> and
 136.784 +     * then <code>{@link #println()}</code>.
 136.785 +     *
 136.786 +     * @param x  an array of chars to print.
 136.787 +     */
 136.788 +    public void println(char x[]) {
 136.789 +        synchronized (this) {
 136.790 +            print(x);
 136.791 +            newLine();
 136.792 +        }
 136.793 +    }
 136.794 +
 136.795 +    /**
 136.796 +     * Prints a String and then terminate the line.  This method behaves as
 136.797 +     * though it invokes <code>{@link #print(String)}</code> and then
 136.798 +     * <code>{@link #println()}</code>.
 136.799 +     *
 136.800 +     * @param x  The <code>String</code> to be printed.
 136.801 +     */
 136.802 +    public void println(String x) {
 136.803 +        synchronized (this) {
 136.804 +            print(x);
 136.805 +            newLine();
 136.806 +        }
 136.807 +    }
 136.808 +
 136.809 +    /**
 136.810 +     * Prints an Object and then terminate the line.  This method calls
 136.811 +     * at first String.valueOf(x) to get the printed object's string value,
 136.812 +     * then behaves as
 136.813 +     * though it invokes <code>{@link #print(String)}</code> and then
 136.814 +     * <code>{@link #println()}</code>.
 136.815 +     *
 136.816 +     * @param x  The <code>Object</code> to be printed.
 136.817 +     */
 136.818 +    public void println(Object x) {
 136.819 +        String s = String.valueOf(x);
 136.820 +        synchronized (this) {
 136.821 +            print(s);
 136.822 +            newLine();
 136.823 +        }
 136.824 +    }
 136.825 +
 136.826 +
 136.827 +    /**
 136.828 +     * A convenience method to write a formatted string to this output stream
 136.829 +     * using the specified format string and arguments.
 136.830 +     *
 136.831 +     * <p> An invocation of this method of the form <tt>out.printf(format,
 136.832 +     * args)</tt> behaves in exactly the same way as the invocation
 136.833 +     *
 136.834 +     * <pre>
 136.835 +     *     out.format(format, args) </pre>
 136.836 +     *
 136.837 +     * @param  format
 136.838 +     *         A format string as described in <a
 136.839 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 136.840 +     *
 136.841 +     * @param  args
 136.842 +     *         Arguments referenced by the format specifiers in the format
 136.843 +     *         string.  If there are more arguments than format specifiers, the
 136.844 +     *         extra arguments are ignored.  The number of arguments is
 136.845 +     *         variable and may be zero.  The maximum number of arguments is
 136.846 +     *         limited by the maximum dimension of a Java array as defined by
 136.847 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 136.848 +     *         The behaviour on a
 136.849 +     *         <tt>null</tt> argument depends on the <a
 136.850 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 136.851 +     *
 136.852 +     * @throws  IllegalFormatException
 136.853 +     *          If a format string contains an illegal syntax, a format
 136.854 +     *          specifier that is incompatible with the given arguments,
 136.855 +     *          insufficient arguments given the format string, or other
 136.856 +     *          illegal conditions.  For specification of all possible
 136.857 +     *          formatting errors, see the <a
 136.858 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 136.859 +     *          formatter class specification.
 136.860 +     *
 136.861 +     * @throws  NullPointerException
 136.862 +     *          If the <tt>format</tt> is <tt>null</tt>
 136.863 +     *
 136.864 +     * @return  This output stream
 136.865 +     *
 136.866 +     * @since  1.5
 136.867 +     */
 136.868 +    public PrintStream printf(String format, Object ... args) {
 136.869 +        append(format).append(Arrays.toString(args));
 136.870 +        return this;
 136.871 +    }
 136.872 +
 136.873 +    /**
 136.874 +     * A convenience method to write a formatted string to this output stream
 136.875 +     * using the specified format string and arguments.
 136.876 +     *
 136.877 +     * <p> An invocation of this method of the form <tt>out.printf(l, format,
 136.878 +     * args)</tt> behaves in exactly the same way as the invocation
 136.879 +     *
 136.880 +     * <pre>
 136.881 +     *     out.format(l, format, args) </pre>
 136.882 +     *
 136.883 +     * @param  l
 136.884 +     *         The {@linkplain java.util.Locale locale} to apply during
 136.885 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 136.886 +     *         is applied.
 136.887 +     *
 136.888 +     * @param  format
 136.889 +     *         A format string as described in <a
 136.890 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 136.891 +     *
 136.892 +     * @param  args
 136.893 +     *         Arguments referenced by the format specifiers in the format
 136.894 +     *         string.  If there are more arguments than format specifiers, the
 136.895 +     *         extra arguments are ignored.  The number of arguments is
 136.896 +     *         variable and may be zero.  The maximum number of arguments is
 136.897 +     *         limited by the maximum dimension of a Java array as defined by
 136.898 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 136.899 +     *         The behaviour on a
 136.900 +     *         <tt>null</tt> argument depends on the <a
 136.901 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 136.902 +     *
 136.903 +     * @throws  IllegalFormatException
 136.904 +     *          If a format string contains an illegal syntax, a format
 136.905 +     *          specifier that is incompatible with the given arguments,
 136.906 +     *          insufficient arguments given the format string, or other
 136.907 +     *          illegal conditions.  For specification of all possible
 136.908 +     *          formatting errors, see the <a
 136.909 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 136.910 +     *          formatter class specification.
 136.911 +     *
 136.912 +     * @throws  NullPointerException
 136.913 +     *          If the <tt>format</tt> is <tt>null</tt>
 136.914 +     *
 136.915 +     * @return  This output stream
 136.916 +     *
 136.917 +     * @since  1.5
 136.918 +     */
 136.919 +//    public PrintStream printf(Locale l, String format, Object ... args) {
 136.920 +//        return format(l, format, args);
 136.921 +//    }
 136.922 +
 136.923 +    /**
 136.924 +     * Writes a formatted string to this output stream using the specified
 136.925 +     * format string and arguments.
 136.926 +     *
 136.927 +     * <p> The locale always used is the one returned by {@link
 136.928 +     * java.util.Locale#getDefault() Locale.getDefault()}, regardless of any
 136.929 +     * previous invocations of other formatting methods on this object.
 136.930 +     *
 136.931 +     * @param  format
 136.932 +     *         A format string as described in <a
 136.933 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 136.934 +     *
 136.935 +     * @param  args
 136.936 +     *         Arguments referenced by the format specifiers in the format
 136.937 +     *         string.  If there are more arguments than format specifiers, the
 136.938 +     *         extra arguments are ignored.  The number of arguments is
 136.939 +     *         variable and may be zero.  The maximum number of arguments is
 136.940 +     *         limited by the maximum dimension of a Java array as defined by
 136.941 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 136.942 +     *         The behaviour on a
 136.943 +     *         <tt>null</tt> argument depends on the <a
 136.944 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 136.945 +     *
 136.946 +     * @throws  IllegalFormatException
 136.947 +     *          If a format string contains an illegal syntax, a format
 136.948 +     *          specifier that is incompatible with the given arguments,
 136.949 +     *          insufficient arguments given the format string, or other
 136.950 +     *          illegal conditions.  For specification of all possible
 136.951 +     *          formatting errors, see the <a
 136.952 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 136.953 +     *          formatter class specification.
 136.954 +     *
 136.955 +     * @throws  NullPointerException
 136.956 +     *          If the <tt>format</tt> is <tt>null</tt>
 136.957 +     *
 136.958 +     * @return  This output stream
 136.959 +     *
 136.960 +     * @since  1.5
 136.961 +     */
 136.962 +//    public PrintStream format(String format, Object ... args) {
 136.963 +//        try {
 136.964 +//            synchronized (this) {
 136.965 +//                ensureOpen();
 136.966 +//                if ((formatter == null)
 136.967 +//                    || (formatter.locale() != Locale.getDefault()))
 136.968 +//                    formatter = new Formatter((Appendable) this);
 136.969 +//                formatter.format(Locale.getDefault(), format, args);
 136.970 +//            }
 136.971 +//        } catch (InterruptedIOException x) {
 136.972 +//            Thread.currentThread().interrupt();
 136.973 +//        } catch (IOException x) {
 136.974 +//            trouble = true;
 136.975 +//        }
 136.976 +//        return this;
 136.977 +//    }
 136.978 +
 136.979 +    /**
 136.980 +     * Writes a formatted string to this output stream using the specified
 136.981 +     * format string and arguments.
 136.982 +     *
 136.983 +     * @param  l
 136.984 +     *         The {@linkplain java.util.Locale locale} to apply during
 136.985 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 136.986 +     *         is applied.
 136.987 +     *
 136.988 +     * @param  format
 136.989 +     *         A format string as described in <a
 136.990 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>
 136.991 +     *
 136.992 +     * @param  args
 136.993 +     *         Arguments referenced by the format specifiers in the format
 136.994 +     *         string.  If there are more arguments than format specifiers, the
 136.995 +     *         extra arguments are ignored.  The number of arguments is
 136.996 +     *         variable and may be zero.  The maximum number of arguments is
 136.997 +     *         limited by the maximum dimension of a Java array as defined by
 136.998 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 136.999 +     *         The behaviour on a
136.1000 +     *         <tt>null</tt> argument depends on the <a
136.1001 +     *         href="../util/Formatter.html#syntax">conversion</a>.
136.1002 +     *
136.1003 +     * @throws  IllegalFormatException
136.1004 +     *          If a format string contains an illegal syntax, a format
136.1005 +     *          specifier that is incompatible with the given arguments,
136.1006 +     *          insufficient arguments given the format string, or other
136.1007 +     *          illegal conditions.  For specification of all possible
136.1008 +     *          formatting errors, see the <a
136.1009 +     *          href="../util/Formatter.html#detail">Details</a> section of the
136.1010 +     *          formatter class specification.
136.1011 +     *
136.1012 +     * @throws  NullPointerException
136.1013 +     *          If the <tt>format</tt> is <tt>null</tt>
136.1014 +     *
136.1015 +     * @return  This output stream
136.1016 +     *
136.1017 +     * @since  1.5
136.1018 +     */
136.1019 +////    public PrintStream format(Locale l, String format, Object ... args) {
136.1020 +////        try {
136.1021 +////            synchronized (this) {
136.1022 +////                ensureOpen();
136.1023 +////                if ((formatter == null)
136.1024 +////                    || (formatter.locale() != l))
136.1025 +////                    formatter = new Formatter(this, l);
136.1026 +////                formatter.format(l, format, args);
136.1027 +////            }
136.1028 +////        } catch (InterruptedIOException x) {
136.1029 +////            Thread.currentThread().interrupt();
136.1030 +////        } catch (IOException x) {
136.1031 +////            trouble = true;
136.1032 +////        }
136.1033 +////        return this;
136.1034 +////    }
136.1035 +
136.1036 +    /**
136.1037 +     * Appends the specified character sequence to this output stream.
136.1038 +     *
136.1039 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
136.1040 +     * behaves in exactly the same way as the invocation
136.1041 +     *
136.1042 +     * <pre>
136.1043 +     *     out.print(csq.toString()) </pre>
136.1044 +     *
136.1045 +     * <p> Depending on the specification of <tt>toString</tt> for the
136.1046 +     * character sequence <tt>csq</tt>, the entire sequence may not be
136.1047 +     * appended.  For instance, invoking then <tt>toString</tt> method of a
136.1048 +     * character buffer will return a subsequence whose content depends upon
136.1049 +     * the buffer's position and limit.
136.1050 +     *
136.1051 +     * @param  csq
136.1052 +     *         The character sequence to append.  If <tt>csq</tt> is
136.1053 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
136.1054 +     *         appended to this output stream.
136.1055 +     *
136.1056 +     * @return  This output stream
136.1057 +     *
136.1058 +     * @since  1.5
136.1059 +     */
136.1060 +    public PrintStream append(CharSequence csq) {
136.1061 +        if (csq == null)
136.1062 +            print("null");
136.1063 +        else
136.1064 +            print(csq.toString());
136.1065 +        return this;
136.1066 +    }
136.1067 +
136.1068 +    /**
136.1069 +     * Appends a subsequence of the specified character sequence to this output
136.1070 +     * stream.
136.1071 +     *
136.1072 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
136.1073 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
136.1074 +     * exactly the same way as the invocation
136.1075 +     *
136.1076 +     * <pre>
136.1077 +     *     out.print(csq.subSequence(start, end).toString()) </pre>
136.1078 +     *
136.1079 +     * @param  csq
136.1080 +     *         The character sequence from which a subsequence will be
136.1081 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
136.1082 +     *         will be appended as if <tt>csq</tt> contained the four
136.1083 +     *         characters <tt>"null"</tt>.
136.1084 +     *
136.1085 +     * @param  start
136.1086 +     *         The index of the first character in the subsequence
136.1087 +     *
136.1088 +     * @param  end
136.1089 +     *         The index of the character following the last character in the
136.1090 +     *         subsequence
136.1091 +     *
136.1092 +     * @return  This output stream
136.1093 +     *
136.1094 +     * @throws  IndexOutOfBoundsException
136.1095 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
136.1096 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
136.1097 +     *          <tt>csq.length()</tt>
136.1098 +     *
136.1099 +     * @since  1.5
136.1100 +     */
136.1101 +    public PrintStream append(CharSequence csq, int start, int end) {
136.1102 +        CharSequence cs = (csq == null ? "null" : csq);
136.1103 +        write(cs.subSequence(start, end).toString());
136.1104 +        return this;
136.1105 +    }
136.1106 +
136.1107 +    /**
136.1108 +     * Appends the specified character to this output stream.
136.1109 +     *
136.1110 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
136.1111 +     * behaves in exactly the same way as the invocation
136.1112 +     *
136.1113 +     * <pre>
136.1114 +     *     out.print(c) </pre>
136.1115 +     *
136.1116 +     * @param  c
136.1117 +     *         The 16-bit character to append
136.1118 +     *
136.1119 +     * @return  This output stream
136.1120 +     *
136.1121 +     * @since  1.5
136.1122 +     */
136.1123 +    public PrintStream append(char c) {
136.1124 +        print(c);
136.1125 +        return this;
136.1126 +    }
136.1127 +
136.1128 +}
   137.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   137.2 +++ b/rt/emul/compact/src/main/java/java/io/PrintWriter.java	Mon Oct 07 14:20:58 2013 +0200
   137.3 @@ -0,0 +1,1030 @@
   137.4 +/*
   137.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   137.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   137.7 + *
   137.8 + * This code is free software; you can redistribute it and/or modify it
   137.9 + * under the terms of the GNU General Public License version 2 only, as
  137.10 + * published by the Free Software Foundation.  Oracle designates this
  137.11 + * particular file as subject to the "Classpath" exception as provided
  137.12 + * by Oracle in the LICENSE file that accompanied this code.
  137.13 + *
  137.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  137.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  137.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  137.17 + * version 2 for more details (a copy is included in the LICENSE file that
  137.18 + * accompanied this code).
  137.19 + *
  137.20 + * You should have received a copy of the GNU General Public License version
  137.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  137.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  137.23 + *
  137.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  137.25 + * or visit www.oracle.com if you need additional information or have any
  137.26 + * questions.
  137.27 + */
  137.28 +
  137.29 +package java.io;
  137.30 +
  137.31 +import java.io.PrintStream.Charset;
  137.32 +import java.io.PrintStream.Formatter;
  137.33 +import java.util.Arrays;
  137.34 +import java.util.Objects;
  137.35 +
  137.36 +/**
  137.37 + * Prints formatted representations of objects to a text-output stream.  This
  137.38 + * class implements all of the <tt>print</tt> methods found in {@link
  137.39 + * PrintStream}.  It does not contain methods for writing raw bytes, for which
  137.40 + * a program should use unencoded byte streams.
  137.41 + *
  137.42 + * <p> Unlike the {@link PrintStream} class, if automatic flushing is enabled
  137.43 + * it will be done only when one of the <tt>println</tt>, <tt>printf</tt>, or
  137.44 + * <tt>format</tt> methods is invoked, rather than whenever a newline character
  137.45 + * happens to be output.  These methods use the platform's own notion of line
  137.46 + * separator rather than the newline character.
  137.47 + *
  137.48 + * <p> Methods in this class never throw I/O exceptions, although some of its
  137.49 + * constructors may.  The client may inquire as to whether any errors have
  137.50 + * occurred by invoking {@link #checkError checkError()}.
  137.51 + *
  137.52 + * @author      Frank Yellin
  137.53 + * @author      Mark Reinhold
  137.54 + * @since       JDK1.1
  137.55 + */
  137.56 +
  137.57 +public class PrintWriter extends Writer {
  137.58 +
  137.59 +    /**
  137.60 +     * The underlying character-output stream of this
  137.61 +     * <code>PrintWriter</code>.
  137.62 +     *
  137.63 +     * @since 1.2
  137.64 +     */
  137.65 +    protected Writer out;
  137.66 +
  137.67 +    private final boolean autoFlush;
  137.68 +    private boolean trouble = false;
  137.69 +    private Formatter formatter;
  137.70 +//    private PrintStream psOut = null;
  137.71 +
  137.72 +    /**
  137.73 +     * Line separator string.  This is the value of the line.separator
  137.74 +     * property at the moment that the stream was created.
  137.75 +     */
  137.76 +    private final String lineSeparator;
  137.77 +
  137.78 +    /**
  137.79 +     * Returns a charset object for the given charset name.
  137.80 +     * @throws NullPointerException          is csn is null
  137.81 +     * @throws UnsupportedEncodingException  if the charset is not supported
  137.82 +     */
  137.83 +    private static Charset toCharset(String csn)
  137.84 +        throws UnsupportedEncodingException
  137.85 +    {
  137.86 +        return PrintStream.toCharset(csn);
  137.87 +    }
  137.88 +
  137.89 +    /**
  137.90 +     * Creates a new PrintWriter, without automatic line flushing.
  137.91 +     *
  137.92 +     * @param  out        A character-output stream
  137.93 +     */
  137.94 +    public PrintWriter (Writer out) {
  137.95 +        this(out, false);
  137.96 +    }
  137.97 +
  137.98 +    /**
  137.99 +     * Creates a new PrintWriter.
 137.100 +     *
 137.101 +     * @param  out        A character-output stream
 137.102 +     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 137.103 +     *                    <tt>printf</tt>, or <tt>format</tt> methods will
 137.104 +     *                    flush the output buffer
 137.105 +     */
 137.106 +    public PrintWriter(Writer out,
 137.107 +                       boolean autoFlush) {
 137.108 +        super(out);
 137.109 +        this.out = out;
 137.110 +        this.autoFlush = autoFlush;
 137.111 +        lineSeparator = "\n";
 137.112 +    }
 137.113 +
 137.114 +    /**
 137.115 +     * Creates a new PrintWriter, without automatic line flushing, from an
 137.116 +     * existing OutputStream.  This convenience constructor creates the
 137.117 +     * necessary intermediate OutputStreamWriter, which will convert characters
 137.118 +     * into bytes using the default character encoding.
 137.119 +     *
 137.120 +     * @param  out        An output stream
 137.121 +     *
 137.122 +     * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 137.123 +     */
 137.124 +    public PrintWriter(OutputStream out) {
 137.125 +        this(out, false);
 137.126 +    }
 137.127 +
 137.128 +    /**
 137.129 +     * Creates a new PrintWriter from an existing OutputStream.  This
 137.130 +     * convenience constructor creates the necessary intermediate
 137.131 +     * OutputStreamWriter, which will convert characters into bytes using the
 137.132 +     * default character encoding.
 137.133 +     *
 137.134 +     * @param  out        An output stream
 137.135 +     * @param  autoFlush  A boolean; if true, the <tt>println</tt>,
 137.136 +     *                    <tt>printf</tt>, or <tt>format</tt> methods will
 137.137 +     *                    flush the output buffer
 137.138 +     *
 137.139 +     * @see java.io.OutputStreamWriter#OutputStreamWriter(java.io.OutputStream)
 137.140 +     */
 137.141 +    public PrintWriter(OutputStream out, boolean autoFlush) {
 137.142 +        this(new BufferedWriter(new OutputStreamWriter(out)), autoFlush);
 137.143 +
 137.144 +        // save print stream for error propagation
 137.145 +//        if (out instanceof java.io.PrintStream) {
 137.146 +//            psOut = (PrintStream) out;
 137.147 +//        }
 137.148 +    }
 137.149 +
 137.150 +    /**
 137.151 +     * Creates a new PrintWriter, without automatic line flushing, with the
 137.152 +     * specified file name.  This convenience constructor creates the necessary
 137.153 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 137.154 +     * which will encode characters using the {@linkplain
 137.155 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 137.156 +     * instance of the Java virtual machine.
 137.157 +     *
 137.158 +     * @param  fileName
 137.159 +     *         The name of the file to use as the destination of this writer.
 137.160 +     *         If the file exists then it will be truncated to zero size;
 137.161 +     *         otherwise, a new file will be created.  The output will be
 137.162 +     *         written to the file and is buffered.
 137.163 +     *
 137.164 +     * @throws  FileNotFoundException
 137.165 +     *          If the given string does not denote an existing, writable
 137.166 +     *          regular file and a new regular file of that name cannot be
 137.167 +     *          created, or if some other error occurs while opening or
 137.168 +     *          creating the file
 137.169 +     *
 137.170 +     * @throws  SecurityException
 137.171 +     *          If a security manager is present and {@link
 137.172 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 137.173 +     *          access to the file
 137.174 +     *
 137.175 +     * @since  1.5
 137.176 +     */
 137.177 +    public PrintWriter(String fileName) throws FileNotFoundException {
 137.178 +        super();
 137.179 +        throw new FileNotFoundException();
 137.180 +    }
 137.181 +
 137.182 +    /* Private constructor */
 137.183 +    private PrintWriter(Charset charset, File file)
 137.184 +        throws FileNotFoundException
 137.185 +    {
 137.186 +        super();
 137.187 +        throw new FileNotFoundException();
 137.188 +    }
 137.189 +
 137.190 +    /**
 137.191 +     * Creates a new PrintWriter, without automatic line flushing, with the
 137.192 +     * specified file name and charset.  This convenience constructor creates
 137.193 +     * the necessary intermediate {@link java.io.OutputStreamWriter
 137.194 +     * OutputStreamWriter}, which will encode characters using the provided
 137.195 +     * charset.
 137.196 +     *
 137.197 +     * @param  fileName
 137.198 +     *         The name of the file to use as the destination of this writer.
 137.199 +     *         If the file exists then it will be truncated to zero size;
 137.200 +     *         otherwise, a new file will be created.  The output will be
 137.201 +     *         written to the file and is buffered.
 137.202 +     *
 137.203 +     * @param  csn
 137.204 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 137.205 +     *         charset}
 137.206 +     *
 137.207 +     * @throws  FileNotFoundException
 137.208 +     *          If the given string does not denote an existing, writable
 137.209 +     *          regular file and a new regular file of that name cannot be
 137.210 +     *          created, or if some other error occurs while opening or
 137.211 +     *          creating the file
 137.212 +     *
 137.213 +     * @throws  SecurityException
 137.214 +     *          If a security manager is present and {@link
 137.215 +     *          SecurityManager#checkWrite checkWrite(fileName)} denies write
 137.216 +     *          access to the file
 137.217 +     *
 137.218 +     * @throws  UnsupportedEncodingException
 137.219 +     *          If the named charset is not supported
 137.220 +     *
 137.221 +     * @since  1.5
 137.222 +     */
 137.223 +    public PrintWriter(String fileName, String csn)
 137.224 +        throws FileNotFoundException, UnsupportedEncodingException
 137.225 +    {
 137.226 +        this(toCharset(csn), new File(fileName));
 137.227 +    }
 137.228 +
 137.229 +    /**
 137.230 +     * Creates a new PrintWriter, without automatic line flushing, with the
 137.231 +     * specified file.  This convenience constructor creates the necessary
 137.232 +     * intermediate {@link java.io.OutputStreamWriter OutputStreamWriter},
 137.233 +     * which will encode characters using the {@linkplain
 137.234 +     * java.nio.charset.Charset#defaultCharset() default charset} for this
 137.235 +     * instance of the Java virtual machine.
 137.236 +     *
 137.237 +     * @param  file
 137.238 +     *         The file to use as the destination of this writer.  If the file
 137.239 +     *         exists then it will be truncated to zero size; otherwise, a new
 137.240 +     *         file will be created.  The output will be written to the file
 137.241 +     *         and is buffered.
 137.242 +     *
 137.243 +     * @throws  FileNotFoundException
 137.244 +     *          If the given file object does not denote an existing, writable
 137.245 +     *          regular file and a new regular file of that name cannot be
 137.246 +     *          created, or if some other error occurs while opening or
 137.247 +     *          creating the file
 137.248 +     *
 137.249 +     * @throws  SecurityException
 137.250 +     *          If a security manager is present and {@link
 137.251 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 137.252 +     *          denies write access to the file
 137.253 +     *
 137.254 +     * @since  1.5
 137.255 +     */
 137.256 +    public PrintWriter(File file) throws FileNotFoundException {
 137.257 +        super();
 137.258 +        throw new FileNotFoundException();
 137.259 +    }
 137.260 +
 137.261 +    /**
 137.262 +     * Creates a new PrintWriter, without automatic line flushing, with the
 137.263 +     * specified file and charset.  This convenience constructor creates the
 137.264 +     * necessary intermediate {@link java.io.OutputStreamWriter
 137.265 +     * OutputStreamWriter}, which will encode characters using the provided
 137.266 +     * charset.
 137.267 +     *
 137.268 +     * @param  file
 137.269 +     *         The file to use as the destination of this writer.  If the file
 137.270 +     *         exists then it will be truncated to zero size; otherwise, a new
 137.271 +     *         file will be created.  The output will be written to the file
 137.272 +     *         and is buffered.
 137.273 +     *
 137.274 +     * @param  csn
 137.275 +     *         The name of a supported {@linkplain java.nio.charset.Charset
 137.276 +     *         charset}
 137.277 +     *
 137.278 +     * @throws  FileNotFoundException
 137.279 +     *          If the given file object does not denote an existing, writable
 137.280 +     *          regular file and a new regular file of that name cannot be
 137.281 +     *          created, or if some other error occurs while opening or
 137.282 +     *          creating the file
 137.283 +     *
 137.284 +     * @throws  SecurityException
 137.285 +     *          If a security manager is present and {@link
 137.286 +     *          SecurityManager#checkWrite checkWrite(file.getPath())}
 137.287 +     *          denies write access to the file
 137.288 +     *
 137.289 +     * @throws  UnsupportedEncodingException
 137.290 +     *          If the named charset is not supported
 137.291 +     *
 137.292 +     * @since  1.5
 137.293 +     */
 137.294 +    public PrintWriter(File file, String csn)
 137.295 +        throws FileNotFoundException, UnsupportedEncodingException
 137.296 +    {
 137.297 +        this(toCharset(csn), file);
 137.298 +    }
 137.299 +
 137.300 +    /** Checks to make sure that the stream has not been closed */
 137.301 +    private void ensureOpen() throws IOException {
 137.302 +        if (out == null)
 137.303 +            throw new IOException("Stream closed");
 137.304 +    }
 137.305 +
 137.306 +    /**
 137.307 +     * Flushes the stream.
 137.308 +     * @see #checkError()
 137.309 +     */
 137.310 +    public void flush() {
 137.311 +        try {
 137.312 +            synchronized (lock) {
 137.313 +                ensureOpen();
 137.314 +                out.flush();
 137.315 +            }
 137.316 +        }
 137.317 +        catch (IOException x) {
 137.318 +            trouble = true;
 137.319 +        }
 137.320 +    }
 137.321 +
 137.322 +    /**
 137.323 +     * Closes the stream and releases any system resources associated
 137.324 +     * with it. Closing a previously closed stream has no effect.
 137.325 +     *
 137.326 +     * @see #checkError()
 137.327 +     */
 137.328 +    public void close() {
 137.329 +        try {
 137.330 +            synchronized (lock) {
 137.331 +                if (out == null)
 137.332 +                    return;
 137.333 +                out.close();
 137.334 +                out = null;
 137.335 +            }
 137.336 +        }
 137.337 +        catch (IOException x) {
 137.338 +            trouble = true;
 137.339 +        }
 137.340 +    }
 137.341 +
 137.342 +    /**
 137.343 +     * Flushes the stream if it's not closed and checks its error state.
 137.344 +     *
 137.345 +     * @return <code>true</code> if the print stream has encountered an error,
 137.346 +     *          either on the underlying output stream or during a format
 137.347 +     *          conversion.
 137.348 +     */
 137.349 +    public boolean checkError() {
 137.350 +        if (out != null) {
 137.351 +            flush();
 137.352 +        }
 137.353 +        if (out instanceof java.io.PrintWriter) {
 137.354 +            PrintWriter pw = (PrintWriter) out;
 137.355 +            return pw.checkError();
 137.356 +        } else 
 137.357 +//        if (psOut != null) {
 137.358 +//            return psOut.checkError();
 137.359 +//        }
 137.360 +        return trouble;
 137.361 +    }
 137.362 +
 137.363 +    /**
 137.364 +     * Indicates that an error has occurred.
 137.365 +     *
 137.366 +     * <p> This method will cause subsequent invocations of {@link
 137.367 +     * #checkError()} to return <tt>true</tt> until {@link
 137.368 +     * #clearError()} is invoked.
 137.369 +     */
 137.370 +    protected void setError() {
 137.371 +        trouble = true;
 137.372 +    }
 137.373 +
 137.374 +    /**
 137.375 +     * Clears the error state of this stream.
 137.376 +     *
 137.377 +     * <p> This method will cause subsequent invocations of {@link
 137.378 +     * #checkError()} to return <tt>false</tt> until another write
 137.379 +     * operation fails and invokes {@link #setError()}.
 137.380 +     *
 137.381 +     * @since 1.6
 137.382 +     */
 137.383 +    protected void clearError() {
 137.384 +        trouble = false;
 137.385 +    }
 137.386 +
 137.387 +    /*
 137.388 +     * Exception-catching, synchronized output operations,
 137.389 +     * which also implement the write() methods of Writer
 137.390 +     */
 137.391 +
 137.392 +    /**
 137.393 +     * Writes a single character.
 137.394 +     * @param c int specifying a character to be written.
 137.395 +     */
 137.396 +    public void write(int c) {
 137.397 +        try {
 137.398 +            synchronized (lock) {
 137.399 +                ensureOpen();
 137.400 +                out.write(c);
 137.401 +            }
 137.402 +        }
 137.403 +        catch (InterruptedIOException x) {
 137.404 +            Thread.currentThread().interrupt();
 137.405 +        }
 137.406 +        catch (IOException x) {
 137.407 +            trouble = true;
 137.408 +        }
 137.409 +    }
 137.410 +
 137.411 +    /**
 137.412 +     * Writes A Portion of an array of characters.
 137.413 +     * @param buf Array of characters
 137.414 +     * @param off Offset from which to start writing characters
 137.415 +     * @param len Number of characters to write
 137.416 +     */
 137.417 +    public void write(char buf[], int off, int len) {
 137.418 +        try {
 137.419 +            synchronized (lock) {
 137.420 +                ensureOpen();
 137.421 +                out.write(buf, off, len);
 137.422 +            }
 137.423 +        }
 137.424 +        catch (InterruptedIOException x) {
 137.425 +            Thread.currentThread().interrupt();
 137.426 +        }
 137.427 +        catch (IOException x) {
 137.428 +            trouble = true;
 137.429 +        }
 137.430 +    }
 137.431 +
 137.432 +    /**
 137.433 +     * Writes an array of characters.  This method cannot be inherited from the
 137.434 +     * Writer class because it must suppress I/O exceptions.
 137.435 +     * @param buf Array of characters to be written
 137.436 +     */
 137.437 +    public void write(char buf[]) {
 137.438 +        write(buf, 0, buf.length);
 137.439 +    }
 137.440 +
 137.441 +    /**
 137.442 +     * Writes a portion of a string.
 137.443 +     * @param s A String
 137.444 +     * @param off Offset from which to start writing characters
 137.445 +     * @param len Number of characters to write
 137.446 +     */
 137.447 +    public void write(String s, int off, int len) {
 137.448 +        try {
 137.449 +            synchronized (lock) {
 137.450 +                ensureOpen();
 137.451 +                out.write(s, off, len);
 137.452 +            }
 137.453 +        }
 137.454 +        catch (InterruptedIOException x) {
 137.455 +            Thread.currentThread().interrupt();
 137.456 +        }
 137.457 +        catch (IOException x) {
 137.458 +            trouble = true;
 137.459 +        }
 137.460 +    }
 137.461 +
 137.462 +    /**
 137.463 +     * Writes a string.  This method cannot be inherited from the Writer class
 137.464 +     * because it must suppress I/O exceptions.
 137.465 +     * @param s String to be written
 137.466 +     */
 137.467 +    public void write(String s) {
 137.468 +        write(s, 0, s.length());
 137.469 +    }
 137.470 +
 137.471 +    private void newLine() {
 137.472 +        try {
 137.473 +            synchronized (lock) {
 137.474 +                ensureOpen();
 137.475 +                out.write(lineSeparator);
 137.476 +                if (autoFlush)
 137.477 +                    out.flush();
 137.478 +            }
 137.479 +        }
 137.480 +        catch (InterruptedIOException x) {
 137.481 +            Thread.currentThread().interrupt();
 137.482 +        }
 137.483 +        catch (IOException x) {
 137.484 +            trouble = true;
 137.485 +        }
 137.486 +    }
 137.487 +
 137.488 +    /* Methods that do not terminate lines */
 137.489 +
 137.490 +    /**
 137.491 +     * Prints a boolean value.  The string produced by <code>{@link
 137.492 +     * java.lang.String#valueOf(boolean)}</code> is translated into bytes
 137.493 +     * according to the platform's default character encoding, and these bytes
 137.494 +     * are written in exactly the manner of the <code>{@link
 137.495 +     * #write(int)}</code> method.
 137.496 +     *
 137.497 +     * @param      b   The <code>boolean</code> to be printed
 137.498 +     */
 137.499 +    public void print(boolean b) {
 137.500 +        write(b ? "true" : "false");
 137.501 +    }
 137.502 +
 137.503 +    /**
 137.504 +     * Prints a character.  The character is translated into one or more bytes
 137.505 +     * according to the platform's default character encoding, and these bytes
 137.506 +     * are written in exactly the manner of the <code>{@link
 137.507 +     * #write(int)}</code> method.
 137.508 +     *
 137.509 +     * @param      c   The <code>char</code> to be printed
 137.510 +     */
 137.511 +    public void print(char c) {
 137.512 +        write(c);
 137.513 +    }
 137.514 +
 137.515 +    /**
 137.516 +     * Prints an integer.  The string produced by <code>{@link
 137.517 +     * java.lang.String#valueOf(int)}</code> is translated into bytes according
 137.518 +     * to the platform's default character encoding, and these bytes are
 137.519 +     * written in exactly the manner of the <code>{@link #write(int)}</code>
 137.520 +     * method.
 137.521 +     *
 137.522 +     * @param      i   The <code>int</code> to be printed
 137.523 +     * @see        java.lang.Integer#toString(int)
 137.524 +     */
 137.525 +    public void print(int i) {
 137.526 +        write(String.valueOf(i));
 137.527 +    }
 137.528 +
 137.529 +    /**
 137.530 +     * Prints a long integer.  The string produced by <code>{@link
 137.531 +     * java.lang.String#valueOf(long)}</code> is translated into bytes
 137.532 +     * according to the platform's default character encoding, and these bytes
 137.533 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 137.534 +     * method.
 137.535 +     *
 137.536 +     * @param      l   The <code>long</code> to be printed
 137.537 +     * @see        java.lang.Long#toString(long)
 137.538 +     */
 137.539 +    public void print(long l) {
 137.540 +        write(String.valueOf(l));
 137.541 +    }
 137.542 +
 137.543 +    /**
 137.544 +     * Prints a floating-point number.  The string produced by <code>{@link
 137.545 +     * java.lang.String#valueOf(float)}</code> is translated into bytes
 137.546 +     * according to the platform's default character encoding, and these bytes
 137.547 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 137.548 +     * method.
 137.549 +     *
 137.550 +     * @param      f   The <code>float</code> to be printed
 137.551 +     * @see        java.lang.Float#toString(float)
 137.552 +     */
 137.553 +    public void print(float f) {
 137.554 +        write(String.valueOf(f));
 137.555 +    }
 137.556 +
 137.557 +    /**
 137.558 +     * Prints a double-precision floating-point number.  The string produced by
 137.559 +     * <code>{@link java.lang.String#valueOf(double)}</code> is translated into
 137.560 +     * bytes according to the platform's default character encoding, and these
 137.561 +     * bytes are written in exactly the manner of the <code>{@link
 137.562 +     * #write(int)}</code> method.
 137.563 +     *
 137.564 +     * @param      d   The <code>double</code> to be printed
 137.565 +     * @see        java.lang.Double#toString(double)
 137.566 +     */
 137.567 +    public void print(double d) {
 137.568 +        write(String.valueOf(d));
 137.569 +    }
 137.570 +
 137.571 +    /**
 137.572 +     * Prints an array of characters.  The characters are converted into bytes
 137.573 +     * according to the platform's default character encoding, and these bytes
 137.574 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 137.575 +     * method.
 137.576 +     *
 137.577 +     * @param      s   The array of chars to be printed
 137.578 +     *
 137.579 +     * @throws  NullPointerException  If <code>s</code> is <code>null</code>
 137.580 +     */
 137.581 +    public void print(char s[]) {
 137.582 +        write(s);
 137.583 +    }
 137.584 +
 137.585 +    /**
 137.586 +     * Prints a string.  If the argument is <code>null</code> then the string
 137.587 +     * <code>"null"</code> is printed.  Otherwise, the string's characters are
 137.588 +     * converted into bytes according to the platform's default character
 137.589 +     * encoding, and these bytes are written in exactly the manner of the
 137.590 +     * <code>{@link #write(int)}</code> method.
 137.591 +     *
 137.592 +     * @param      s   The <code>String</code> to be printed
 137.593 +     */
 137.594 +    public void print(String s) {
 137.595 +        if (s == null) {
 137.596 +            s = "null";
 137.597 +        }
 137.598 +        write(s);
 137.599 +    }
 137.600 +
 137.601 +    /**
 137.602 +     * Prints an object.  The string produced by the <code>{@link
 137.603 +     * java.lang.String#valueOf(Object)}</code> method is translated into bytes
 137.604 +     * according to the platform's default character encoding, and these bytes
 137.605 +     * are written in exactly the manner of the <code>{@link #write(int)}</code>
 137.606 +     * method.
 137.607 +     *
 137.608 +     * @param      obj   The <code>Object</code> to be printed
 137.609 +     * @see        java.lang.Object#toString()
 137.610 +     */
 137.611 +    public void print(Object obj) {
 137.612 +        write(String.valueOf(obj));
 137.613 +    }
 137.614 +
 137.615 +    /* Methods that do terminate lines */
 137.616 +
 137.617 +    /**
 137.618 +     * Terminates the current line by writing the line separator string.  The
 137.619 +     * line separator string is defined by the system property
 137.620 +     * <code>line.separator</code>, and is not necessarily a single newline
 137.621 +     * character (<code>'\n'</code>).
 137.622 +     */
 137.623 +    public void println() {
 137.624 +        newLine();
 137.625 +    }
 137.626 +
 137.627 +    /**
 137.628 +     * Prints a boolean value and then terminates the line.  This method behaves
 137.629 +     * as though it invokes <code>{@link #print(boolean)}</code> and then
 137.630 +     * <code>{@link #println()}</code>.
 137.631 +     *
 137.632 +     * @param x the <code>boolean</code> value to be printed
 137.633 +     */
 137.634 +    public void println(boolean x) {
 137.635 +        synchronized (lock) {
 137.636 +            print(x);
 137.637 +            println();
 137.638 +        }
 137.639 +    }
 137.640 +
 137.641 +    /**
 137.642 +     * Prints a character and then terminates the line.  This method behaves as
 137.643 +     * though it invokes <code>{@link #print(char)}</code> and then <code>{@link
 137.644 +     * #println()}</code>.
 137.645 +     *
 137.646 +     * @param x the <code>char</code> value to be printed
 137.647 +     */
 137.648 +    public void println(char x) {
 137.649 +        synchronized (lock) {
 137.650 +            print(x);
 137.651 +            println();
 137.652 +        }
 137.653 +    }
 137.654 +
 137.655 +    /**
 137.656 +     * Prints an integer and then terminates the line.  This method behaves as
 137.657 +     * though it invokes <code>{@link #print(int)}</code> and then <code>{@link
 137.658 +     * #println()}</code>.
 137.659 +     *
 137.660 +     * @param x the <code>int</code> value to be printed
 137.661 +     */
 137.662 +    public void println(int x) {
 137.663 +        synchronized (lock) {
 137.664 +            print(x);
 137.665 +            println();
 137.666 +        }
 137.667 +    }
 137.668 +
 137.669 +    /**
 137.670 +     * Prints a long integer and then terminates the line.  This method behaves
 137.671 +     * as though it invokes <code>{@link #print(long)}</code> and then
 137.672 +     * <code>{@link #println()}</code>.
 137.673 +     *
 137.674 +     * @param x the <code>long</code> value to be printed
 137.675 +     */
 137.676 +    public void println(long x) {
 137.677 +        synchronized (lock) {
 137.678 +            print(x);
 137.679 +            println();
 137.680 +        }
 137.681 +    }
 137.682 +
 137.683 +    /**
 137.684 +     * Prints a floating-point number and then terminates the line.  This method
 137.685 +     * behaves as though it invokes <code>{@link #print(float)}</code> and then
 137.686 +     * <code>{@link #println()}</code>.
 137.687 +     *
 137.688 +     * @param x the <code>float</code> value to be printed
 137.689 +     */
 137.690 +    public void println(float x) {
 137.691 +        synchronized (lock) {
 137.692 +            print(x);
 137.693 +            println();
 137.694 +        }
 137.695 +    }
 137.696 +
 137.697 +    /**
 137.698 +     * Prints a double-precision floating-point number and then terminates the
 137.699 +     * line.  This method behaves as though it invokes <code>{@link
 137.700 +     * #print(double)}</code> and then <code>{@link #println()}</code>.
 137.701 +     *
 137.702 +     * @param x the <code>double</code> value to be printed
 137.703 +     */
 137.704 +    public void println(double x) {
 137.705 +        synchronized (lock) {
 137.706 +            print(x);
 137.707 +            println();
 137.708 +        }
 137.709 +    }
 137.710 +
 137.711 +    /**
 137.712 +     * Prints an array of characters and then terminates the line.  This method
 137.713 +     * behaves as though it invokes <code>{@link #print(char[])}</code> and then
 137.714 +     * <code>{@link #println()}</code>.
 137.715 +     *
 137.716 +     * @param x the array of <code>char</code> values to be printed
 137.717 +     */
 137.718 +    public void println(char x[]) {
 137.719 +        synchronized (lock) {
 137.720 +            print(x);
 137.721 +            println();
 137.722 +        }
 137.723 +    }
 137.724 +
 137.725 +    /**
 137.726 +     * Prints a String and then terminates the line.  This method behaves as
 137.727 +     * though it invokes <code>{@link #print(String)}</code> and then
 137.728 +     * <code>{@link #println()}</code>.
 137.729 +     *
 137.730 +     * @param x the <code>String</code> value to be printed
 137.731 +     */
 137.732 +    public void println(String x) {
 137.733 +        synchronized (lock) {
 137.734 +            print(x);
 137.735 +            println();
 137.736 +        }
 137.737 +    }
 137.738 +
 137.739 +    /**
 137.740 +     * Prints an Object and then terminates the line.  This method calls
 137.741 +     * at first String.valueOf(x) to get the printed object's string value,
 137.742 +     * then behaves as
 137.743 +     * though it invokes <code>{@link #print(String)}</code> and then
 137.744 +     * <code>{@link #println()}</code>.
 137.745 +     *
 137.746 +     * @param x  The <code>Object</code> to be printed.
 137.747 +     */
 137.748 +    public void println(Object x) {
 137.749 +        String s = String.valueOf(x);
 137.750 +        synchronized (lock) {
 137.751 +            print(s);
 137.752 +            println();
 137.753 +        }
 137.754 +    }
 137.755 +
 137.756 +    /**
 137.757 +     * A convenience method to write a formatted string to this writer using
 137.758 +     * the specified format string and arguments.  If automatic flushing is
 137.759 +     * enabled, calls to this method will flush the output buffer.
 137.760 +     *
 137.761 +     * <p> An invocation of this method of the form <tt>out.printf(format,
 137.762 +     * args)</tt> behaves in exactly the same way as the invocation
 137.763 +     *
 137.764 +     * <pre>
 137.765 +     *     out.format(format, args) </pre>
 137.766 +     *
 137.767 +     * @param  format
 137.768 +     *         A format string as described in <a
 137.769 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 137.770 +     *
 137.771 +     * @param  args
 137.772 +     *         Arguments referenced by the format specifiers in the format
 137.773 +     *         string.  If there are more arguments than format specifiers, the
 137.774 +     *         extra arguments are ignored.  The number of arguments is
 137.775 +     *         variable and may be zero.  The maximum number of arguments is
 137.776 +     *         limited by the maximum dimension of a Java array as defined by
 137.777 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 137.778 +     *         The behaviour on a
 137.779 +     *         <tt>null</tt> argument depends on the <a
 137.780 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 137.781 +     *
 137.782 +     * @throws  IllegalFormatException
 137.783 +     *          If a format string contains an illegal syntax, a format
 137.784 +     *          specifier that is incompatible with the given arguments,
 137.785 +     *          insufficient arguments given the format string, or other
 137.786 +     *          illegal conditions.  For specification of all possible
 137.787 +     *          formatting errors, see the <a
 137.788 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 137.789 +     *          formatter class specification.
 137.790 +     *
 137.791 +     * @throws  NullPointerException
 137.792 +     *          If the <tt>format</tt> is <tt>null</tt>
 137.793 +     *
 137.794 +     * @return  This writer
 137.795 +     *
 137.796 +     * @since  1.5
 137.797 +     */
 137.798 +    public PrintWriter printf(String format, Object ... args) {
 137.799 +        return format(format, args);
 137.800 +    }
 137.801 +
 137.802 +    /**
 137.803 +     * A convenience method to write a formatted string to this writer using
 137.804 +     * the specified format string and arguments.  If automatic flushing is
 137.805 +     * enabled, calls to this method will flush the output buffer.
 137.806 +     *
 137.807 +     * <p> An invocation of this method of the form <tt>out.printf(l, format,
 137.808 +     * args)</tt> behaves in exactly the same way as the invocation
 137.809 +     *
 137.810 +     * <pre>
 137.811 +     *     out.format(l, format, args) </pre>
 137.812 +     *
 137.813 +     * @param  l
 137.814 +     *         The {@linkplain java.util.Locale locale} to apply during
 137.815 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 137.816 +     *         is applied.
 137.817 +     *
 137.818 +     * @param  format
 137.819 +     *         A format string as described in <a
 137.820 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 137.821 +     *
 137.822 +     * @param  args
 137.823 +     *         Arguments referenced by the format specifiers in the format
 137.824 +     *         string.  If there are more arguments than format specifiers, the
 137.825 +     *         extra arguments are ignored.  The number of arguments is
 137.826 +     *         variable and may be zero.  The maximum number of arguments is
 137.827 +     *         limited by the maximum dimension of a Java array as defined by
 137.828 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 137.829 +     *         The behaviour on a
 137.830 +     *         <tt>null</tt> argument depends on the <a
 137.831 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 137.832 +     *
 137.833 +     * @throws  IllegalFormatException
 137.834 +     *          If a format string contains an illegal syntax, a format
 137.835 +     *          specifier that is incompatible with the given arguments,
 137.836 +     *          insufficient arguments given the format string, or other
 137.837 +     *          illegal conditions.  For specification of all possible
 137.838 +     *          formatting errors, see the <a
 137.839 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 137.840 +     *          formatter class specification.
 137.841 +     *
 137.842 +     * @throws  NullPointerException
 137.843 +     *          If the <tt>format</tt> is <tt>null</tt>
 137.844 +     *
 137.845 +     * @return  This writer
 137.846 +     *
 137.847 +     * @since  1.5
 137.848 +     */
 137.849 +//    public PrintWriter printf(Locale l, String format, Object ... args) {
 137.850 +//        return format(l, format, args);
 137.851 +//    }
 137.852 +
 137.853 +    /**
 137.854 +     * Writes a formatted string to this writer using the specified format
 137.855 +     * string and arguments.  If automatic flushing is enabled, calls to this
 137.856 +     * method will flush the output buffer.
 137.857 +     *
 137.858 +     * <p> The locale always used is the one returned by {@link
 137.859 +     * java.util.Locale#getDefault() Locale.getDefault()}, regardless of any
 137.860 +     * previous invocations of other formatting methods on this object.
 137.861 +     *
 137.862 +     * @param  format
 137.863 +     *         A format string as described in <a
 137.864 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 137.865 +     *
 137.866 +     * @param  args
 137.867 +     *         Arguments referenced by the format specifiers in the format
 137.868 +     *         string.  If there are more arguments than format specifiers, the
 137.869 +     *         extra arguments are ignored.  The number of arguments is
 137.870 +     *         variable and may be zero.  The maximum number of arguments is
 137.871 +     *         limited by the maximum dimension of a Java array as defined by
 137.872 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 137.873 +     *         The behaviour on a
 137.874 +     *         <tt>null</tt> argument depends on the <a
 137.875 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 137.876 +     *
 137.877 +     * @throws  IllegalFormatException
 137.878 +     *          If a format string contains an illegal syntax, a format
 137.879 +     *          specifier that is incompatible with the given arguments,
 137.880 +     *          insufficient arguments given the format string, or other
 137.881 +     *          illegal conditions.  For specification of all possible
 137.882 +     *          formatting errors, see the <a
 137.883 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 137.884 +     *          Formatter class specification.
 137.885 +     *
 137.886 +     * @throws  NullPointerException
 137.887 +     *          If the <tt>format</tt> is <tt>null</tt>
 137.888 +     *
 137.889 +     * @return  This writer
 137.890 +     *
 137.891 +     * @since  1.5
 137.892 +     */
 137.893 +    public PrintWriter format(String format, Object ... args) {
 137.894 +        append(format).append(Arrays.toString(args));
 137.895 +        return this;
 137.896 +    }
 137.897 +
 137.898 +    /**
 137.899 +     * Writes a formatted string to this writer using the specified format
 137.900 +     * string and arguments.  If automatic flushing is enabled, calls to this
 137.901 +     * method will flush the output buffer.
 137.902 +     *
 137.903 +     * @param  l
 137.904 +     *         The {@linkplain java.util.Locale locale} to apply during
 137.905 +     *         formatting.  If <tt>l</tt> is <tt>null</tt> then no localization
 137.906 +     *         is applied.
 137.907 +     *
 137.908 +     * @param  format
 137.909 +     *         A format string as described in <a
 137.910 +     *         href="../util/Formatter.html#syntax">Format string syntax</a>.
 137.911 +     *
 137.912 +     * @param  args
 137.913 +     *         Arguments referenced by the format specifiers in the format
 137.914 +     *         string.  If there are more arguments than format specifiers, the
 137.915 +     *         extra arguments are ignored.  The number of arguments is
 137.916 +     *         variable and may be zero.  The maximum number of arguments is
 137.917 +     *         limited by the maximum dimension of a Java array as defined by
 137.918 +     *         <cite>The Java&trade; Virtual Machine Specification</cite>.
 137.919 +     *         The behaviour on a
 137.920 +     *         <tt>null</tt> argument depends on the <a
 137.921 +     *         href="../util/Formatter.html#syntax">conversion</a>.
 137.922 +     *
 137.923 +     * @throws  IllegalFormatException
 137.924 +     *          If a format string contains an illegal syntax, a format
 137.925 +     *          specifier that is incompatible with the given arguments,
 137.926 +     *          insufficient arguments given the format string, or other
 137.927 +     *          illegal conditions.  For specification of all possible
 137.928 +     *          formatting errors, see the <a
 137.929 +     *          href="../util/Formatter.html#detail">Details</a> section of the
 137.930 +     *          formatter class specification.
 137.931 +     *
 137.932 +     * @throws  NullPointerException
 137.933 +     *          If the <tt>format</tt> is <tt>null</tt>
 137.934 +     *
 137.935 +     * @return  This writer
 137.936 +     *
 137.937 +     * @since  1.5
 137.938 +     */
 137.939 +//    public PrintWriter format(Locale l, String format, Object ... args) {
 137.940 +//        return format(format, args);
 137.941 +//    }
 137.942 +
 137.943 +    /**
 137.944 +     * Appends the specified character sequence to this writer.
 137.945 +     *
 137.946 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
 137.947 +     * behaves in exactly the same way as the invocation
 137.948 +     *
 137.949 +     * <pre>
 137.950 +     *     out.write(csq.toString()) </pre>
 137.951 +     *
 137.952 +     * <p> Depending on the specification of <tt>toString</tt> for the
 137.953 +     * character sequence <tt>csq</tt>, the entire sequence may not be
 137.954 +     * appended. For instance, invoking the <tt>toString</tt> method of a
 137.955 +     * character buffer will return a subsequence whose content depends upon
 137.956 +     * the buffer's position and limit.
 137.957 +     *
 137.958 +     * @param  csq
 137.959 +     *         The character sequence to append.  If <tt>csq</tt> is
 137.960 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
 137.961 +     *         appended to this writer.
 137.962 +     *
 137.963 +     * @return  This writer
 137.964 +     *
 137.965 +     * @since  1.5
 137.966 +     */
 137.967 +    public PrintWriter append(CharSequence csq) {
 137.968 +        if (csq == null)
 137.969 +            write("null");
 137.970 +        else
 137.971 +            write(csq.toString());
 137.972 +        return this;
 137.973 +    }
 137.974 +
 137.975 +    /**
 137.976 +     * Appends a subsequence of the specified character sequence to this writer.
 137.977 +     *
 137.978 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
 137.979 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt>, behaves in
 137.980 +     * exactly the same way as the invocation
 137.981 +     *
 137.982 +     * <pre>
 137.983 +     *     out.write(csq.subSequence(start, end).toString()) </pre>
 137.984 +     *
 137.985 +     * @param  csq
 137.986 +     *         The character sequence from which a subsequence will be
 137.987 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
 137.988 +     *         will be appended as if <tt>csq</tt> contained the four
 137.989 +     *         characters <tt>"null"</tt>.
 137.990 +     *
 137.991 +     * @param  start
 137.992 +     *         The index of the first character in the subsequence
 137.993 +     *
 137.994 +     * @param  end
 137.995 +     *         The index of the character following the last character in the
 137.996 +     *         subsequence
 137.997 +     *
 137.998 +     * @return  This writer
 137.999 +     *
137.1000 +     * @throws  IndexOutOfBoundsException
137.1001 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
137.1002 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
137.1003 +     *          <tt>csq.length()</tt>
137.1004 +     *
137.1005 +     * @since  1.5
137.1006 +     */
137.1007 +    public PrintWriter append(CharSequence csq, int start, int end) {
137.1008 +        CharSequence cs = (csq == null ? "null" : csq);
137.1009 +        write(cs.subSequence(start, end).toString());
137.1010 +        return this;
137.1011 +    }
137.1012 +
137.1013 +    /**
137.1014 +     * Appends the specified character to this writer.
137.1015 +     *
137.1016 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
137.1017 +     * behaves in exactly the same way as the invocation
137.1018 +     *
137.1019 +     * <pre>
137.1020 +     *     out.write(c) </pre>
137.1021 +     *
137.1022 +     * @param  c
137.1023 +     *         The 16-bit character to append
137.1024 +     *
137.1025 +     * @return  This writer
137.1026 +     *
137.1027 +     * @since 1.5
137.1028 +     */
137.1029 +    public PrintWriter append(char c) {
137.1030 +        write(c);
137.1031 +        return this;
137.1032 +    }
137.1033 +}
   138.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   138.2 +++ b/rt/emul/compact/src/main/java/java/io/Writer.java	Mon Oct 07 14:20:58 2013 +0200
   138.3 @@ -0,0 +1,325 @@
   138.4 +/*
   138.5 + * Copyright (c) 1996, 2005, Oracle and/or its affiliates. All rights reserved.
   138.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   138.7 + *
   138.8 + * This code is free software; you can redistribute it and/or modify it
   138.9 + * under the terms of the GNU General Public License version 2 only, as
  138.10 + * published by the Free Software Foundation.  Oracle designates this
  138.11 + * particular file as subject to the "Classpath" exception as provided
  138.12 + * by Oracle in the LICENSE file that accompanied this code.
  138.13 + *
  138.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  138.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  138.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  138.17 + * version 2 for more details (a copy is included in the LICENSE file that
  138.18 + * accompanied this code).
  138.19 + *
  138.20 + * You should have received a copy of the GNU General Public License version
  138.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  138.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  138.23 + *
  138.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  138.25 + * or visit www.oracle.com if you need additional information or have any
  138.26 + * questions.
  138.27 + */
  138.28 +
  138.29 +package java.io;
  138.30 +
  138.31 +
  138.32 +/**
  138.33 + * Abstract class for writing to character streams.  The only methods that a
  138.34 + * subclass must implement are write(char[], int, int), flush(), and close().
  138.35 + * Most subclasses, however, will override some of the methods defined here in
  138.36 + * order to provide higher efficiency, additional functionality, or both.
  138.37 + *
  138.38 + * @see Writer
  138.39 + * @see   BufferedWriter
  138.40 + * @see   CharArrayWriter
  138.41 + * @see   FilterWriter
  138.42 + * @see   OutputStreamWriter
  138.43 + * @see     FileWriter
  138.44 + * @see   PipedWriter
  138.45 + * @see   PrintWriter
  138.46 + * @see   StringWriter
  138.47 + * @see Reader
  138.48 + *
  138.49 + * @author      Mark Reinhold
  138.50 + * @since       JDK1.1
  138.51 + */
  138.52 +
  138.53 +public abstract class Writer implements Appendable, Closeable, Flushable {
  138.54 +
  138.55 +    /**
  138.56 +     * Temporary buffer used to hold writes of strings and single characters
  138.57 +     */
  138.58 +    private char[] writeBuffer;
  138.59 +
  138.60 +    /**
  138.61 +     * Size of writeBuffer, must be >= 1
  138.62 +     */
  138.63 +    private final int writeBufferSize = 1024;
  138.64 +
  138.65 +    /**
  138.66 +     * The object used to synchronize operations on this stream.  For
  138.67 +     * efficiency, a character-stream object may use an object other than
  138.68 +     * itself to protect critical sections.  A subclass should therefore use
  138.69 +     * the object in this field rather than <tt>this</tt> or a synchronized
  138.70 +     * method.
  138.71 +     */
  138.72 +    protected Object lock;
  138.73 +
  138.74 +    /**
  138.75 +     * Creates a new character-stream writer whose critical sections will
  138.76 +     * synchronize on the writer itself.
  138.77 +     */
  138.78 +    protected Writer() {
  138.79 +        this.lock = this;
  138.80 +    }
  138.81 +
  138.82 +    /**
  138.83 +     * Creates a new character-stream writer whose critical sections will
  138.84 +     * synchronize on the given object.
  138.85 +     *
  138.86 +     * @param  lock
  138.87 +     *         Object to synchronize on
  138.88 +     */
  138.89 +    protected Writer(Object lock) {
  138.90 +        if (lock == null) {
  138.91 +            throw new NullPointerException();
  138.92 +        }
  138.93 +        this.lock = lock;
  138.94 +    }
  138.95 +
  138.96 +    /**
  138.97 +     * Writes a single character.  The character to be written is contained in
  138.98 +     * the 16 low-order bits of the given integer value; the 16 high-order bits
  138.99 +     * are ignored.
 138.100 +     *
 138.101 +     * <p> Subclasses that intend to support efficient single-character output
 138.102 +     * should override this method.
 138.103 +     *
 138.104 +     * @param  c
 138.105 +     *         int specifying a character to be written
 138.106 +     *
 138.107 +     * @throws  IOException
 138.108 +     *          If an I/O error occurs
 138.109 +     */
 138.110 +    public void write(int c) throws IOException {
 138.111 +        synchronized (lock) {
 138.112 +            if (writeBuffer == null){
 138.113 +                writeBuffer = new char[writeBufferSize];
 138.114 +            }
 138.115 +            writeBuffer[0] = (char) c;
 138.116 +            write(writeBuffer, 0, 1);
 138.117 +        }
 138.118 +    }
 138.119 +
 138.120 +    /**
 138.121 +     * Writes an array of characters.
 138.122 +     *
 138.123 +     * @param  cbuf
 138.124 +     *         Array of characters to be written
 138.125 +     *
 138.126 +     * @throws  IOException
 138.127 +     *          If an I/O error occurs
 138.128 +     */
 138.129 +    public void write(char cbuf[]) throws IOException {
 138.130 +        write(cbuf, 0, cbuf.length);
 138.131 +    }
 138.132 +
 138.133 +    /**
 138.134 +     * Writes a portion of an array of characters.
 138.135 +     *
 138.136 +     * @param  cbuf
 138.137 +     *         Array of characters
 138.138 +     *
 138.139 +     * @param  off
 138.140 +     *         Offset from which to start writing characters
 138.141 +     *
 138.142 +     * @param  len
 138.143 +     *         Number of characters to write
 138.144 +     *
 138.145 +     * @throws  IOException
 138.146 +     *          If an I/O error occurs
 138.147 +     */
 138.148 +    abstract public void write(char cbuf[], int off, int len) throws IOException;
 138.149 +
 138.150 +    /**
 138.151 +     * Writes a string.
 138.152 +     *
 138.153 +     * @param  str
 138.154 +     *         String to be written
 138.155 +     *
 138.156 +     * @throws  IOException
 138.157 +     *          If an I/O error occurs
 138.158 +     */
 138.159 +    public void write(String str) throws IOException {
 138.160 +        write(str, 0, str.length());
 138.161 +    }
 138.162 +
 138.163 +    /**
 138.164 +     * Writes a portion of a string.
 138.165 +     *
 138.166 +     * @param  str
 138.167 +     *         A String
 138.168 +     *
 138.169 +     * @param  off
 138.170 +     *         Offset from which to start writing characters
 138.171 +     *
 138.172 +     * @param  len
 138.173 +     *         Number of characters to write
 138.174 +     *
 138.175 +     * @throws  IndexOutOfBoundsException
 138.176 +     *          If <tt>off</tt> is negative, or <tt>len</tt> is negative,
 138.177 +     *          or <tt>off+len</tt> is negative or greater than the length
 138.178 +     *          of the given string
 138.179 +     *
 138.180 +     * @throws  IOException
 138.181 +     *          If an I/O error occurs
 138.182 +     */
 138.183 +    public void write(String str, int off, int len) throws IOException {
 138.184 +        synchronized (lock) {
 138.185 +            char cbuf[];
 138.186 +            if (len <= writeBufferSize) {
 138.187 +                if (writeBuffer == null) {
 138.188 +                    writeBuffer = new char[writeBufferSize];
 138.189 +                }
 138.190 +                cbuf = writeBuffer;
 138.191 +            } else {    // Don't permanently allocate very large buffers.
 138.192 +                cbuf = new char[len];
 138.193 +            }
 138.194 +            str.getChars(off, (off + len), cbuf, 0);
 138.195 +            write(cbuf, 0, len);
 138.196 +        }
 138.197 +    }
 138.198 +
 138.199 +    /**
 138.200 +     * Appends the specified character sequence to this writer.
 138.201 +     *
 138.202 +     * <p> An invocation of this method of the form <tt>out.append(csq)</tt>
 138.203 +     * behaves in exactly the same way as the invocation
 138.204 +     *
 138.205 +     * <pre>
 138.206 +     *     out.write(csq.toString()) </pre>
 138.207 +     *
 138.208 +     * <p> Depending on the specification of <tt>toString</tt> for the
 138.209 +     * character sequence <tt>csq</tt>, the entire sequence may not be
 138.210 +     * appended. For instance, invoking the <tt>toString</tt> method of a
 138.211 +     * character buffer will return a subsequence whose content depends upon
 138.212 +     * the buffer's position and limit.
 138.213 +     *
 138.214 +     * @param  csq
 138.215 +     *         The character sequence to append.  If <tt>csq</tt> is
 138.216 +     *         <tt>null</tt>, then the four characters <tt>"null"</tt> are
 138.217 +     *         appended to this writer.
 138.218 +     *
 138.219 +     * @return  This writer
 138.220 +     *
 138.221 +     * @throws  IOException
 138.222 +     *          If an I/O error occurs
 138.223 +     *
 138.224 +     * @since  1.5
 138.225 +     */
 138.226 +    public Writer append(CharSequence csq) throws IOException {
 138.227 +        if (csq == null)
 138.228 +            write("null");
 138.229 +        else
 138.230 +            write(csq.toString());
 138.231 +        return this;
 138.232 +    }
 138.233 +
 138.234 +    /**
 138.235 +     * Appends a subsequence of the specified character sequence to this writer.
 138.236 +     * <tt>Appendable</tt>.
 138.237 +     *
 138.238 +     * <p> An invocation of this method of the form <tt>out.append(csq, start,
 138.239 +     * end)</tt> when <tt>csq</tt> is not <tt>null</tt> behaves in exactly the
 138.240 +     * same way as the invocation
 138.241 +     *
 138.242 +     * <pre>
 138.243 +     *     out.write(csq.subSequence(start, end).toString()) </pre>
 138.244 +     *
 138.245 +     * @param  csq
 138.246 +     *         The character sequence from which a subsequence will be
 138.247 +     *         appended.  If <tt>csq</tt> is <tt>null</tt>, then characters
 138.248 +     *         will be appended as if <tt>csq</tt> contained the four
 138.249 +     *         characters <tt>"null"</tt>.
 138.250 +     *
 138.251 +     * @param  start
 138.252 +     *         The index of the first character in the subsequence
 138.253 +     *
 138.254 +     * @param  end
 138.255 +     *         The index of the character following the last character in the
 138.256 +     *         subsequence
 138.257 +     *
 138.258 +     * @return  This writer
 138.259 +     *
 138.260 +     * @throws  IndexOutOfBoundsException
 138.261 +     *          If <tt>start</tt> or <tt>end</tt> are negative, <tt>start</tt>
 138.262 +     *          is greater than <tt>end</tt>, or <tt>end</tt> is greater than
 138.263 +     *          <tt>csq.length()</tt>
 138.264 +     *
 138.265 +     * @throws  IOException
 138.266 +     *          If an I/O error occurs
 138.267 +     *
 138.268 +     * @since  1.5
 138.269 +     */
 138.270 +    public Writer append(CharSequence csq, int start, int end) throws IOException {
 138.271 +        CharSequence cs = (csq == null ? "null" : csq);
 138.272 +        write(cs.subSequence(start, end).toString());
 138.273 +        return this;
 138.274 +    }
 138.275 +
 138.276 +    /**
 138.277 +     * Appends the specified character to this writer.
 138.278 +     *
 138.279 +     * <p> An invocation of this method of the form <tt>out.append(c)</tt>
 138.280 +     * behaves in exactly the same way as the invocation
 138.281 +     *
 138.282 +     * <pre>
 138.283 +     *     out.write(c) </pre>
 138.284 +     *
 138.285 +     * @param  c
 138.286 +     *         The 16-bit character to append
 138.287 +     *
 138.288 +     * @return  This writer
 138.289 +     *
 138.290 +     * @throws  IOException
 138.291 +     *          If an I/O error occurs
 138.292 +     *
 138.293 +     * @since 1.5
 138.294 +     */
 138.295 +    public Writer append(char c) throws IOException {
 138.296 +        write(c);
 138.297 +        return this;
 138.298 +    }
 138.299 +
 138.300 +    /**
 138.301 +     * Flushes the stream.  If the stream has saved any characters from the
 138.302 +     * various write() methods in a buffer, write them immediately to their
 138.303 +     * intended destination.  Then, if that destination is another character or
 138.304 +     * byte stream, flush it.  Thus one flush() invocation will flush all the
 138.305 +     * buffers in a chain of Writers and OutputStreams.
 138.306 +     *
 138.307 +     * <p> If the intended destination of this stream is an abstraction provided
 138.308 +     * by the underlying operating system, for example a file, then flushing the
 138.309 +     * stream guarantees only that bytes previously written to the stream are
 138.310 +     * passed to the operating system for writing; it does not guarantee that
 138.311 +     * they are actually written to a physical device such as a disk drive.
 138.312 +     *
 138.313 +     * @throws  IOException
 138.314 +     *          If an I/O error occurs
 138.315 +     */
 138.316 +    abstract public void flush() throws IOException;
 138.317 +
 138.318 +    /**
 138.319 +     * Closes the stream, flushing it first. Once the stream has been closed,
 138.320 +     * further write() or flush() invocations will cause an IOException to be
 138.321 +     * thrown. Closing a previously closed stream has no effect.
 138.322 +     *
 138.323 +     * @throws  IOException
 138.324 +     *          If an I/O error occurs
 138.325 +     */
 138.326 +    abstract public void close() throws IOException;
 138.327 +
 138.328 +}
   139.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   139.2 +++ b/rt/emul/compact/src/main/java/java/lang/StackOverflowError.java	Mon Oct 07 14:20:58 2013 +0200
   139.3 @@ -0,0 +1,55 @@
   139.4 +/*
   139.5 + * Copyright (c) 1994, 2008, Oracle and/or its affiliates. All rights reserved.
   139.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   139.7 + *
   139.8 + * This code is free software; you can redistribute it and/or modify it
   139.9 + * under the terms of the GNU General Public License version 2 only, as
  139.10 + * published by the Free Software Foundation.  Oracle designates this
  139.11 + * particular file as subject to the "Classpath" exception as provided
  139.12 + * by Oracle in the LICENSE file that accompanied this code.
  139.13 + *
  139.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  139.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  139.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  139.17 + * version 2 for more details (a copy is included in the LICENSE file that
  139.18 + * accompanied this code).
  139.19 + *
  139.20 + * You should have received a copy of the GNU General Public License version
  139.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  139.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  139.23 + *
  139.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  139.25 + * or visit www.oracle.com if you need additional information or have any
  139.26 + * questions.
  139.27 + */
  139.28 +
  139.29 +package java.lang;
  139.30 +
  139.31 +/**
  139.32 + * Thrown when a stack overflow occurs because an application
  139.33 + * recurses too deeply.
  139.34 + *
  139.35 + * @author unascribed
  139.36 + * @since   JDK1.0
  139.37 + */
  139.38 +public
  139.39 +class StackOverflowError extends VirtualMachineError {
  139.40 +    private static final long serialVersionUID = 8609175038441759607L;
  139.41 +
  139.42 +    /**
  139.43 +     * Constructs a <code>StackOverflowError</code> with no detail message.
  139.44 +     */
  139.45 +    public StackOverflowError() {
  139.46 +        super();
  139.47 +    }
  139.48 +
  139.49 +    /**
  139.50 +     * Constructs a <code>StackOverflowError</code> with the specified
  139.51 +     * detail message.
  139.52 +     *
  139.53 +     * @param   s   the detail message.
  139.54 +     */
  139.55 +    public StackOverflowError(String s) {
  139.56 +        super(s);
  139.57 +    }
  139.58 +}
   140.1 --- a/rt/emul/compact/src/main/java/java/lang/System.java	Wed Feb 27 17:50:47 2013 +0100
   140.2 +++ b/rt/emul/compact/src/main/java/java/lang/System.java	Mon Oct 07 14:20:58 2013 +0200
   140.3 @@ -17,6 +17,8 @@
   140.4   */
   140.5  package java.lang;
   140.6  
   140.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   140.8 +
   140.9  /** Poor man's re-implementation of most important System methods.
  140.10   *
  140.11   * @author Jaroslav Tulach <jtulach@netbeans.org>
  140.12 @@ -33,4 +35,31 @@
  140.13          return org.apidesign.bck2brwsr.emul.lang.System.currentTimeMillis();
  140.14      }
  140.15      
  140.16 +    public static int identityHashCode(Object obj) {
  140.17 +        return obj.defaultHashCode();
  140.18 +    }
  140.19 +
  140.20 +    public static String getProperty(String name) {
  140.21 +        return null;
  140.22 +    }
  140.23 +    
  140.24 +    public static String getProperty(String key, String def) {
  140.25 +        return def;
  140.26 +    }
  140.27 +    
  140.28 +    /**
  140.29 +     * Returns the system-dependent line separator string.  It always
  140.30 +     * returns the same value - the initial value of the {@linkplain
  140.31 +     * #getProperty(String) system property} {@code line.separator}.
  140.32 +     *
  140.33 +     * <p>On UNIX systems, it returns {@code "\n"}; on Microsoft
  140.34 +     * Windows systems it returns {@code "\r\n"}.
  140.35 +     */
  140.36 +    public static String lineSeparator() {
  140.37 +        return "\n";
  140.38 +    }
  140.39 +
  140.40 +    @JavaScriptBody(args = { "exitCode" }, body = "window.close();")
  140.41 +    public static void exit(int exitCode) {
  140.42 +    }
  140.43  }
   141.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   141.2 +++ b/rt/emul/compact/src/main/java/java/lang/Thread.java	Mon Oct 07 14:20:58 2013 +0200
   141.3 @@ -0,0 +1,1544 @@
   141.4 +/*
   141.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
   141.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   141.7 + *
   141.8 + * This code is free software; you can redistribute it and/or modify it
   141.9 + * under the terms of the GNU General Public License version 2 only, as
  141.10 + * published by the Free Software Foundation.  Oracle designates this
  141.11 + * particular file as subject to the "Classpath" exception as provided
  141.12 + * by Oracle in the LICENSE file that accompanied this code.
  141.13 + *
  141.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  141.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  141.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  141.17 + * version 2 for more details (a copy is included in the LICENSE file that
  141.18 + * accompanied this code).
  141.19 + *
  141.20 + * You should have received a copy of the GNU General Public License version
  141.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  141.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  141.23 + *
  141.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  141.25 + * or visit www.oracle.com if you need additional information or have any
  141.26 + * questions.
  141.27 + */
  141.28 +
  141.29 +package java.lang;
  141.30 +
  141.31 +import java.util.Map;
  141.32 +
  141.33 +
  141.34 +/**
  141.35 + * A <i>thread</i> is a thread of execution in a program. The Java
  141.36 + * Virtual Machine allows an application to have multiple threads of
  141.37 + * execution running concurrently.
  141.38 + * <p>
  141.39 + * Every thread has a priority. Threads with higher priority are
  141.40 + * executed in preference to threads with lower priority. Each thread
  141.41 + * may or may not also be marked as a daemon. When code running in
  141.42 + * some thread creates a new <code>Thread</code> object, the new
  141.43 + * thread has its priority initially set equal to the priority of the
  141.44 + * creating thread, and is a daemon thread if and only if the
  141.45 + * creating thread is a daemon.
  141.46 + * <p>
  141.47 + * When a Java Virtual Machine starts up, there is usually a single
  141.48 + * non-daemon thread (which typically calls the method named
  141.49 + * <code>main</code> of some designated class). The Java Virtual
  141.50 + * Machine continues to execute threads until either of the following
  141.51 + * occurs:
  141.52 + * <ul>
  141.53 + * <li>The <code>exit</code> method of class <code>Runtime</code> has been
  141.54 + *     called and the security manager has permitted the exit operation
  141.55 + *     to take place.
  141.56 + * <li>All threads that are not daemon threads have died, either by
  141.57 + *     returning from the call to the <code>run</code> method or by
  141.58 + *     throwing an exception that propagates beyond the <code>run</code>
  141.59 + *     method.
  141.60 + * </ul>
  141.61 + * <p>
  141.62 + * There are two ways to create a new thread of execution. One is to
  141.63 + * declare a class to be a subclass of <code>Thread</code>. This
  141.64 + * subclass should override the <code>run</code> method of class
  141.65 + * <code>Thread</code>. An instance of the subclass can then be
  141.66 + * allocated and started. For example, a thread that computes primes
  141.67 + * larger than a stated value could be written as follows:
  141.68 + * <p><hr><blockquote><pre>
  141.69 + *     class PrimeThread extends Thread {
  141.70 + *         long minPrime;
  141.71 + *         PrimeThread(long minPrime) {
  141.72 + *             this.minPrime = minPrime;
  141.73 + *         }
  141.74 + *
  141.75 + *         public void run() {
  141.76 + *             // compute primes larger than minPrime
  141.77 + *             &nbsp;.&nbsp;.&nbsp;.
  141.78 + *         }
  141.79 + *     }
  141.80 + * </pre></blockquote><hr>
  141.81 + * <p>
  141.82 + * The following code would then create a thread and start it running:
  141.83 + * <p><blockquote><pre>
  141.84 + *     PrimeThread p = new PrimeThread(143);
  141.85 + *     p.start();
  141.86 + * </pre></blockquote>
  141.87 + * <p>
  141.88 + * The other way to create a thread is to declare a class that
  141.89 + * implements the <code>Runnable</code> interface. That class then
  141.90 + * implements the <code>run</code> method. An instance of the class can
  141.91 + * then be allocated, passed as an argument when creating
  141.92 + * <code>Thread</code>, and started. The same example in this other
  141.93 + * style looks like the following:
  141.94 + * <p><hr><blockquote><pre>
  141.95 + *     class PrimeRun implements Runnable {
  141.96 + *         long minPrime;
  141.97 + *         PrimeRun(long minPrime) {
  141.98 + *             this.minPrime = minPrime;
  141.99 + *         }
 141.100 + *
 141.101 + *         public void run() {
 141.102 + *             // compute primes larger than minPrime
 141.103 + *             &nbsp;.&nbsp;.&nbsp;.
 141.104 + *         }
 141.105 + *     }
 141.106 + * </pre></blockquote><hr>
 141.107 + * <p>
 141.108 + * The following code would then create a thread and start it running:
 141.109 + * <p><blockquote><pre>
 141.110 + *     PrimeRun p = new PrimeRun(143);
 141.111 + *     new Thread(p).start();
 141.112 + * </pre></blockquote>
 141.113 + * <p>
 141.114 + * Every thread has a name for identification purposes. More than
 141.115 + * one thread may have the same name. If a name is not specified when
 141.116 + * a thread is created, a new name is generated for it.
 141.117 + * <p>
 141.118 + * Unless otherwise noted, passing a {@code null} argument to a constructor
 141.119 + * or method in this class will cause a {@link NullPointerException} to be
 141.120 + * thrown.
 141.121 + *
 141.122 + * @author  unascribed
 141.123 + * @see     Runnable
 141.124 + * @see     Runtime#exit(int)
 141.125 + * @see     #run()
 141.126 + * @see     #stop()
 141.127 + * @since   JDK1.0
 141.128 + */
 141.129 +public
 141.130 +class Thread implements Runnable {
 141.131 +
 141.132 +    /**
 141.133 +     * The minimum priority that a thread can have.
 141.134 +     */
 141.135 +    public final static int MIN_PRIORITY = 1;
 141.136 +
 141.137 +   /**
 141.138 +     * The default priority that is assigned to a thread.
 141.139 +     */
 141.140 +    public final static int NORM_PRIORITY = 5;
 141.141 +
 141.142 +    /**
 141.143 +     * The maximum priority that a thread can have.
 141.144 +     */
 141.145 +    public final static int MAX_PRIORITY = 10;
 141.146 +
 141.147 +    private static final Thread ONE = new Thread("main");
 141.148 +    /**
 141.149 +     * Returns a reference to the currently executing thread object.
 141.150 +     *
 141.151 +     * @return  the currently executing thread.
 141.152 +     */
 141.153 +    public static Thread currentThread() {
 141.154 +        return ONE;
 141.155 +    }
 141.156 +
 141.157 +    /**
 141.158 +     * A hint to the scheduler that the current thread is willing to yield
 141.159 +     * its current use of a processor. The scheduler is free to ignore this
 141.160 +     * hint.
 141.161 +     *
 141.162 +     * <p> Yield is a heuristic attempt to improve relative progression
 141.163 +     * between threads that would otherwise over-utilise a CPU. Its use
 141.164 +     * should be combined with detailed profiling and benchmarking to
 141.165 +     * ensure that it actually has the desired effect.
 141.166 +     *
 141.167 +     * <p> It is rarely appropriate to use this method. It may be useful
 141.168 +     * for debugging or testing purposes, where it may help to reproduce
 141.169 +     * bugs due to race conditions. It may also be useful when designing
 141.170 +     * concurrency control constructs such as the ones in the
 141.171 +     * {@link java.util.concurrent.locks} package.
 141.172 +     */
 141.173 +    public static void yield() {
 141.174 +    }
 141.175 +
 141.176 +    /**
 141.177 +     * Causes the currently executing thread to sleep (temporarily cease
 141.178 +     * execution) for the specified number of milliseconds, subject to
 141.179 +     * the precision and accuracy of system timers and schedulers. The thread
 141.180 +     * does not lose ownership of any monitors.
 141.181 +     *
 141.182 +     * @param  millis
 141.183 +     *         the length of time to sleep in milliseconds
 141.184 +     *
 141.185 +     * @throws  IllegalArgumentException
 141.186 +     *          if the value of {@code millis} is negative
 141.187 +     *
 141.188 +     * @throws  InterruptedException
 141.189 +     *          if any thread has interrupted the current thread. The
 141.190 +     *          <i>interrupted status</i> of the current thread is
 141.191 +     *          cleared when this exception is thrown.
 141.192 +     */
 141.193 +    public static native void sleep(long millis) throws InterruptedException;
 141.194 +
 141.195 +    /**
 141.196 +     * Causes the currently executing thread to sleep (temporarily cease
 141.197 +     * execution) for the specified number of milliseconds plus the specified
 141.198 +     * number of nanoseconds, subject to the precision and accuracy of system
 141.199 +     * timers and schedulers. The thread does not lose ownership of any
 141.200 +     * monitors.
 141.201 +     *
 141.202 +     * @param  millis
 141.203 +     *         the length of time to sleep in milliseconds
 141.204 +     *
 141.205 +     * @param  nanos
 141.206 +     *         {@code 0-999999} additional nanoseconds to sleep
 141.207 +     *
 141.208 +     * @throws  IllegalArgumentException
 141.209 +     *          if the value of {@code millis} is negative, or the value of
 141.210 +     *          {@code nanos} is not in the range {@code 0-999999}
 141.211 +     *
 141.212 +     * @throws  InterruptedException
 141.213 +     *          if any thread has interrupted the current thread. The
 141.214 +     *          <i>interrupted status</i> of the current thread is
 141.215 +     *          cleared when this exception is thrown.
 141.216 +     */
 141.217 +    public static void sleep(long millis, int nanos)
 141.218 +    throws InterruptedException {
 141.219 +        if (millis < 0) {
 141.220 +            throw new IllegalArgumentException("timeout value is negative");
 141.221 +        }
 141.222 +
 141.223 +        if (nanos < 0 || nanos > 999999) {
 141.224 +            throw new IllegalArgumentException(
 141.225 +                                "nanosecond timeout value out of range");
 141.226 +        }
 141.227 +
 141.228 +        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
 141.229 +            millis++;
 141.230 +        }
 141.231 +
 141.232 +        sleep(millis);
 141.233 +    }
 141.234 +    private Runnable target;
 141.235 +    private String name;
 141.236 +
 141.237 +    /**
 141.238 +     * Throws CloneNotSupportedException as a Thread can not be meaningfully
 141.239 +     * cloned. Construct a new Thread instead.
 141.240 +     *
 141.241 +     * @throws  CloneNotSupportedException
 141.242 +     *          always
 141.243 +     */
 141.244 +    @Override
 141.245 +    protected Object clone() throws CloneNotSupportedException {
 141.246 +        throw new CloneNotSupportedException();
 141.247 +    }
 141.248 +
 141.249 +    /**
 141.250 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.251 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.252 +     * {@code (null, null, gname)}, where {@code gname} is a newly generated
 141.253 +     * name. Automatically generated names are of the form
 141.254 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 141.255 +     */
 141.256 +    public Thread() {
 141.257 +        init(null, null, "Thread-" + nextThreadNum(), 0);
 141.258 +    }
 141.259 +    
 141.260 +    private static int nextThreadNum() {
 141.261 +        return -1;
 141.262 +    }
 141.263 +
 141.264 +    /**
 141.265 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.266 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.267 +     * {@code (null, target, gname)}, where {@code gname} is a newly generated
 141.268 +     * name. Automatically generated names are of the form
 141.269 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 141.270 +     *
 141.271 +     * @param  target
 141.272 +     *         the object whose {@code run} method is invoked when this thread
 141.273 +     *         is started. If {@code null}, this classes {@code run} method does
 141.274 +     *         nothing.
 141.275 +     */
 141.276 +    public Thread(Runnable target) {
 141.277 +        init(null, target, "Thread-" + nextThreadNum(), 0);
 141.278 +    }
 141.279 +
 141.280 +    /**
 141.281 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.282 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.283 +     * {@code (group, target, gname)} ,where {@code gname} is a newly generated
 141.284 +     * name. Automatically generated names are of the form
 141.285 +     * {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
 141.286 +     *
 141.287 +     * @param  group
 141.288 +     *         the thread group. If {@code null} and there is a security
 141.289 +     *         manager, the group is determined by {@linkplain
 141.290 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 141.291 +     *         If there is not a security manager or {@code
 141.292 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 141.293 +     *         is set to the current thread's thread group.
 141.294 +     *
 141.295 +     * @param  target
 141.296 +     *         the object whose {@code run} method is invoked when this thread
 141.297 +     *         is started. If {@code null}, this thread's run method is invoked.
 141.298 +     *
 141.299 +     * @throws  SecurityException
 141.300 +     *          if the current thread cannot create a thread in the specified
 141.301 +     *          thread group
 141.302 +     */
 141.303 +//    public Thread(ThreadGroup group, Runnable target) {
 141.304 +//        init(group, target, "Thread-" + nextThreadNum(), 0);
 141.305 +//    }
 141.306 +
 141.307 +    /**
 141.308 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.309 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.310 +     * {@code (null, null, name)}.
 141.311 +     *
 141.312 +     * @param   name
 141.313 +     *          the name of the new thread
 141.314 +     */
 141.315 +    public Thread(String name) {
 141.316 +        init(null, null, name, 0);
 141.317 +    }
 141.318 +    
 141.319 +    private void init(Object o1, Runnable trgt, String nm, int i4) {
 141.320 +        this.target = trgt;
 141.321 +        this.name = nm;
 141.322 +    }
 141.323 +
 141.324 +    /**
 141.325 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.326 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.327 +     * {@code (group, null, name)}.
 141.328 +     *
 141.329 +     * @param  group
 141.330 +     *         the thread group. If {@code null} and there is a security
 141.331 +     *         manager, the group is determined by {@linkplain
 141.332 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 141.333 +     *         If there is not a security manager or {@code
 141.334 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 141.335 +     *         is set to the current thread's thread group.
 141.336 +     *
 141.337 +     * @param  name
 141.338 +     *         the name of the new thread
 141.339 +     *
 141.340 +     * @throws  SecurityException
 141.341 +     *          if the current thread cannot create a thread in the specified
 141.342 +     *          thread group
 141.343 +     */
 141.344 +//    public Thread(ThreadGroup group, String name) {
 141.345 +//        init(group, null, name, 0);
 141.346 +//    }
 141.347 +
 141.348 +    /**
 141.349 +     * Allocates a new {@code Thread} object. This constructor has the same
 141.350 +     * effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
 141.351 +     * {@code (null, target, name)}.
 141.352 +     *
 141.353 +     * @param  target
 141.354 +     *         the object whose {@code run} method is invoked when this thread
 141.355 +     *         is started. If {@code null}, this thread's run method is invoked.
 141.356 +     *
 141.357 +     * @param  name
 141.358 +     *         the name of the new thread
 141.359 +     */
 141.360 +    public Thread(Runnable target, String name) {
 141.361 +        init(null, target, name, 0);
 141.362 +    }
 141.363 +
 141.364 +    /**
 141.365 +     * Allocates a new {@code Thread} object so that it has {@code target}
 141.366 +     * as its run object, has the specified {@code name} as its name,
 141.367 +     * and belongs to the thread group referred to by {@code group}.
 141.368 +     *
 141.369 +     * <p>If there is a security manager, its
 141.370 +     * {@link SecurityManager#checkAccess(ThreadGroup) checkAccess}
 141.371 +     * method is invoked with the ThreadGroup as its argument.
 141.372 +     *
 141.373 +     * <p>In addition, its {@code checkPermission} method is invoked with
 141.374 +     * the {@code RuntimePermission("enableContextClassLoaderOverride")}
 141.375 +     * permission when invoked directly or indirectly by the constructor
 141.376 +     * of a subclass which overrides the {@code getContextClassLoader}
 141.377 +     * or {@code setContextClassLoader} methods.
 141.378 +     *
 141.379 +     * <p>The priority of the newly created thread is set equal to the
 141.380 +     * priority of the thread creating it, that is, the currently running
 141.381 +     * thread. The method {@linkplain #setPriority setPriority} may be
 141.382 +     * used to change the priority to a new value.
 141.383 +     *
 141.384 +     * <p>The newly created thread is initially marked as being a daemon
 141.385 +     * thread if and only if the thread creating it is currently marked
 141.386 +     * as a daemon thread. The method {@linkplain #setDaemon setDaemon}
 141.387 +     * may be used to change whether or not a thread is a daemon.
 141.388 +     *
 141.389 +     * @param  group
 141.390 +     *         the thread group. If {@code null} and there is a security
 141.391 +     *         manager, the group is determined by {@linkplain
 141.392 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 141.393 +     *         If there is not a security manager or {@code
 141.394 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 141.395 +     *         is set to the current thread's thread group.
 141.396 +     *
 141.397 +     * @param  target
 141.398 +     *         the object whose {@code run} method is invoked when this thread
 141.399 +     *         is started. If {@code null}, this thread's run method is invoked.
 141.400 +     *
 141.401 +     * @param  name
 141.402 +     *         the name of the new thread
 141.403 +     *
 141.404 +     * @throws  SecurityException
 141.405 +     *          if the current thread cannot create a thread in the specified
 141.406 +     *          thread group or cannot override the context class loader methods.
 141.407 +     */
 141.408 +//    public Thread(ThreadGroup group, Runnable target, String name) {
 141.409 +//        init(group, target, name, 0);
 141.410 +//    }
 141.411 +
 141.412 +    /**
 141.413 +     * Allocates a new {@code Thread} object so that it has {@code target}
 141.414 +     * as its run object, has the specified {@code name} as its name,
 141.415 +     * and belongs to the thread group referred to by {@code group}, and has
 141.416 +     * the specified <i>stack size</i>.
 141.417 +     *
 141.418 +     * <p>This constructor is identical to {@link
 141.419 +     * #Thread(ThreadGroup,Runnable,String)} with the exception of the fact
 141.420 +     * that it allows the thread stack size to be specified.  The stack size
 141.421 +     * is the approximate number of bytes of address space that the virtual
 141.422 +     * machine is to allocate for this thread's stack.  <b>The effect of the
 141.423 +     * {@code stackSize} parameter, if any, is highly platform dependent.</b>
 141.424 +     *
 141.425 +     * <p>On some platforms, specifying a higher value for the
 141.426 +     * {@code stackSize} parameter may allow a thread to achieve greater
 141.427 +     * recursion depth before throwing a {@link StackOverflowError}.
 141.428 +     * Similarly, specifying a lower value may allow a greater number of
 141.429 +     * threads to exist concurrently without throwing an {@link
 141.430 +     * OutOfMemoryError} (or other internal error).  The details of
 141.431 +     * the relationship between the value of the <tt>stackSize</tt> parameter
 141.432 +     * and the maximum recursion depth and concurrency level are
 141.433 +     * platform-dependent.  <b>On some platforms, the value of the
 141.434 +     * {@code stackSize} parameter may have no effect whatsoever.</b>
 141.435 +     *
 141.436 +     * <p>The virtual machine is free to treat the {@code stackSize}
 141.437 +     * parameter as a suggestion.  If the specified value is unreasonably low
 141.438 +     * for the platform, the virtual machine may instead use some
 141.439 +     * platform-specific minimum value; if the specified value is unreasonably
 141.440 +     * high, the virtual machine may instead use some platform-specific
 141.441 +     * maximum.  Likewise, the virtual machine is free to round the specified
 141.442 +     * value up or down as it sees fit (or to ignore it completely).
 141.443 +     *
 141.444 +     * <p>Specifying a value of zero for the {@code stackSize} parameter will
 141.445 +     * cause this constructor to behave exactly like the
 141.446 +     * {@code Thread(ThreadGroup, Runnable, String)} constructor.
 141.447 +     *
 141.448 +     * <p><i>Due to the platform-dependent nature of the behavior of this
 141.449 +     * constructor, extreme care should be exercised in its use.
 141.450 +     * The thread stack size necessary to perform a given computation will
 141.451 +     * likely vary from one JRE implementation to another.  In light of this
 141.452 +     * variation, careful tuning of the stack size parameter may be required,
 141.453 +     * and the tuning may need to be repeated for each JRE implementation on
 141.454 +     * which an application is to run.</i>
 141.455 +     *
 141.456 +     * <p>Implementation note: Java platform implementers are encouraged to
 141.457 +     * document their implementation's behavior with respect to the
 141.458 +     * {@code stackSize} parameter.
 141.459 +     *
 141.460 +     *
 141.461 +     * @param  group
 141.462 +     *         the thread group. If {@code null} and there is a security
 141.463 +     *         manager, the group is determined by {@linkplain
 141.464 +     *         SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
 141.465 +     *         If there is not a security manager or {@code
 141.466 +     *         SecurityManager.getThreadGroup()} returns {@code null}, the group
 141.467 +     *         is set to the current thread's thread group.
 141.468 +     *
 141.469 +     * @param  target
 141.470 +     *         the object whose {@code run} method is invoked when this thread
 141.471 +     *         is started. If {@code null}, this thread's run method is invoked.
 141.472 +     *
 141.473 +     * @param  name
 141.474 +     *         the name of the new thread
 141.475 +     *
 141.476 +     * @param  stackSize
 141.477 +     *         the desired stack size for the new thread, or zero to indicate
 141.478 +     *         that this parameter is to be ignored.
 141.479 +     *
 141.480 +     * @throws  SecurityException
 141.481 +     *          if the current thread cannot create a thread in the specified
 141.482 +     *          thread group
 141.483 +     *
 141.484 +     * @since 1.4
 141.485 +     */
 141.486 +//    public Thread(ThreadGroup group, Runnable target, String name,
 141.487 +//                  long stackSize) {
 141.488 +//        init(group, target, name, stackSize);
 141.489 +//    }
 141.490 +
 141.491 +    /**
 141.492 +     * Causes this thread to begin execution; the Java Virtual Machine
 141.493 +     * calls the <code>run</code> method of this thread.
 141.494 +     * <p>
 141.495 +     * The result is that two threads are running concurrently: the
 141.496 +     * current thread (which returns from the call to the
 141.497 +     * <code>start</code> method) and the other thread (which executes its
 141.498 +     * <code>run</code> method).
 141.499 +     * <p>
 141.500 +     * It is never legal to start a thread more than once.
 141.501 +     * In particular, a thread may not be restarted once it has completed
 141.502 +     * execution.
 141.503 +     *
 141.504 +     * @exception  IllegalThreadStateException  if the thread was already
 141.505 +     *               started.
 141.506 +     * @see        #run()
 141.507 +     * @see        #stop()
 141.508 +     */
 141.509 +    public void start() {
 141.510 +        throw new SecurityException();
 141.511 +    }
 141.512 +
 141.513 +    /**
 141.514 +     * If this thread was constructed using a separate
 141.515 +     * <code>Runnable</code> run object, then that
 141.516 +     * <code>Runnable</code> object's <code>run</code> method is called;
 141.517 +     * otherwise, this method does nothing and returns.
 141.518 +     * <p>
 141.519 +     * Subclasses of <code>Thread</code> should override this method.
 141.520 +     *
 141.521 +     * @see     #start()
 141.522 +     * @see     #stop()
 141.523 +     * @see     #Thread(ThreadGroup, Runnable, String)
 141.524 +     */
 141.525 +    @Override
 141.526 +    public void run() {
 141.527 +        if (target != null) {
 141.528 +            target.run();
 141.529 +        }
 141.530 +    }
 141.531 +
 141.532 +    /**
 141.533 +     * Forces the thread to stop executing.
 141.534 +     * <p>
 141.535 +     * If there is a security manager installed, its <code>checkAccess</code>
 141.536 +     * method is called with <code>this</code>
 141.537 +     * as its argument. This may result in a
 141.538 +     * <code>SecurityException</code> being raised (in the current thread).
 141.539 +     * <p>
 141.540 +     * If this thread is different from the current thread (that is, the current
 141.541 +     * thread is trying to stop a thread other than itself), the
 141.542 +     * security manager's <code>checkPermission</code> method (with a
 141.543 +     * <code>RuntimePermission("stopThread")</code> argument) is called in
 141.544 +     * addition.
 141.545 +     * Again, this may result in throwing a
 141.546 +     * <code>SecurityException</code> (in the current thread).
 141.547 +     * <p>
 141.548 +     * The thread represented by this thread is forced to stop whatever
 141.549 +     * it is doing abnormally and to throw a newly created
 141.550 +     * <code>ThreadDeath</code> object as an exception.
 141.551 +     * <p>
 141.552 +     * It is permitted to stop a thread that has not yet been started.
 141.553 +     * If the thread is eventually started, it immediately terminates.
 141.554 +     * <p>
 141.555 +     * An application should not normally try to catch
 141.556 +     * <code>ThreadDeath</code> unless it must do some extraordinary
 141.557 +     * cleanup operation (note that the throwing of
 141.558 +     * <code>ThreadDeath</code> causes <code>finally</code> clauses of
 141.559 +     * <code>try</code> statements to be executed before the thread
 141.560 +     * officially dies).  If a <code>catch</code> clause catches a
 141.561 +     * <code>ThreadDeath</code> object, it is important to rethrow the
 141.562 +     * object so that the thread actually dies.
 141.563 +     * <p>
 141.564 +     * The top-level error handler that reacts to otherwise uncaught
 141.565 +     * exceptions does not print out a message or otherwise notify the
 141.566 +     * application if the uncaught exception is an instance of
 141.567 +     * <code>ThreadDeath</code>.
 141.568 +     *
 141.569 +     * @exception  SecurityException  if the current thread cannot
 141.570 +     *               modify this thread.
 141.571 +     * @see        #interrupt()
 141.572 +     * @see        #checkAccess()
 141.573 +     * @see        #run()
 141.574 +     * @see        #start()
 141.575 +     * @see        ThreadDeath
 141.576 +     * @see        ThreadGroup#uncaughtException(Thread,Throwable)
 141.577 +     * @see        SecurityManager#checkAccess(Thread)
 141.578 +     * @see        SecurityManager#checkPermission
 141.579 +     * @deprecated This method is inherently unsafe.  Stopping a thread with
 141.580 +     *       Thread.stop causes it to unlock all of the monitors that it
 141.581 +     *       has locked (as a natural consequence of the unchecked
 141.582 +     *       <code>ThreadDeath</code> exception propagating up the stack).  If
 141.583 +     *       any of the objects previously protected by these monitors were in
 141.584 +     *       an inconsistent state, the damaged objects become visible to
 141.585 +     *       other threads, potentially resulting in arbitrary behavior.  Many
 141.586 +     *       uses of <code>stop</code> should be replaced by code that simply
 141.587 +     *       modifies some variable to indicate that the target thread should
 141.588 +     *       stop running.  The target thread should check this variable
 141.589 +     *       regularly, and return from its run method in an orderly fashion
 141.590 +     *       if the variable indicates that it is to stop running.  If the
 141.591 +     *       target thread waits for long periods (on a condition variable,
 141.592 +     *       for example), the <code>interrupt</code> method should be used to
 141.593 +     *       interrupt the wait.
 141.594 +     *       For more information, see
 141.595 +     *       <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 141.596 +     *       are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 141.597 +     */
 141.598 +    @Deprecated
 141.599 +    public final void stop() {
 141.600 +        stop(null);
 141.601 +    }
 141.602 +
 141.603 +    /**
 141.604 +     * Forces the thread to stop executing.
 141.605 +     * <p>
 141.606 +     * If there is a security manager installed, the <code>checkAccess</code>
 141.607 +     * method of this thread is called, which may result in a
 141.608 +     * <code>SecurityException</code> being raised (in the current thread).
 141.609 +     * <p>
 141.610 +     * If this thread is different from the current thread (that is, the current
 141.611 +     * thread is trying to stop a thread other than itself) or
 141.612 +     * <code>obj</code> is not an instance of <code>ThreadDeath</code>, the
 141.613 +     * security manager's <code>checkPermission</code> method (with the
 141.614 +     * <code>RuntimePermission("stopThread")</code> argument) is called in
 141.615 +     * addition.
 141.616 +     * Again, this may result in throwing a
 141.617 +     * <code>SecurityException</code> (in the current thread).
 141.618 +     * <p>
 141.619 +     * If the argument <code>obj</code> is null, a
 141.620 +     * <code>NullPointerException</code> is thrown (in the current thread).
 141.621 +     * <p>
 141.622 +     * The thread represented by this thread is forced to stop
 141.623 +     * whatever it is doing abnormally and to throw the
 141.624 +     * <code>Throwable</code> object <code>obj</code> as an exception. This
 141.625 +     * is an unusual action to take; normally, the <code>stop</code> method
 141.626 +     * that takes no arguments should be used.
 141.627 +     * <p>
 141.628 +     * It is permitted to stop a thread that has not yet been started.
 141.629 +     * If the thread is eventually started, it immediately terminates.
 141.630 +     *
 141.631 +     * @param      obj   the Throwable object to be thrown.
 141.632 +     * @exception  SecurityException  if the current thread cannot modify
 141.633 +     *               this thread.
 141.634 +     * @throws     NullPointerException if obj is <tt>null</tt>.
 141.635 +     * @see        #interrupt()
 141.636 +     * @see        #checkAccess()
 141.637 +     * @see        #run()
 141.638 +     * @see        #start()
 141.639 +     * @see        #stop()
 141.640 +     * @see        SecurityManager#checkAccess(Thread)
 141.641 +     * @see        SecurityManager#checkPermission
 141.642 +     * @deprecated This method is inherently unsafe.  See {@link #stop()}
 141.643 +     *        for details.  An additional danger of this
 141.644 +     *        method is that it may be used to generate exceptions that the
 141.645 +     *        target thread is unprepared to handle (including checked
 141.646 +     *        exceptions that the thread could not possibly throw, were it
 141.647 +     *        not for this method).
 141.648 +     *        For more information, see
 141.649 +     *        <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 141.650 +     *        are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 141.651 +     */
 141.652 +    @Deprecated
 141.653 +    public final synchronized void stop(Throwable obj) {
 141.654 +        throw new SecurityException();
 141.655 +    }
 141.656 +
 141.657 +    /**
 141.658 +     * Interrupts this thread.
 141.659 +     *
 141.660 +     * <p> Unless the current thread is interrupting itself, which is
 141.661 +     * always permitted, the {@link #checkAccess() checkAccess} method
 141.662 +     * of this thread is invoked, which may cause a {@link
 141.663 +     * SecurityException} to be thrown.
 141.664 +     *
 141.665 +     * <p> If this thread is blocked in an invocation of the {@link
 141.666 +     * Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
 141.667 +     * Object#wait(long, int) wait(long, int)} methods of the {@link Object}
 141.668 +     * class, or of the {@link #join()}, {@link #join(long)}, {@link
 141.669 +     * #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
 141.670 +     * methods of this class, then its interrupt status will be cleared and it
 141.671 +     * will receive an {@link InterruptedException}.
 141.672 +     *
 141.673 +     * <p> If this thread is blocked in an I/O operation upon an {@link
 141.674 +     * java.nio.channels.InterruptibleChannel </code>interruptible
 141.675 +     * channel<code>} then the channel will be closed, the thread's interrupt
 141.676 +     * status will be set, and the thread will receive a {@link
 141.677 +     * java.nio.channels.ClosedByInterruptException}.
 141.678 +     *
 141.679 +     * <p> If this thread is blocked in a {@link java.nio.channels.Selector}
 141.680 +     * then the thread's interrupt status will be set and it will return
 141.681 +     * immediately from the selection operation, possibly with a non-zero
 141.682 +     * value, just as if the selector's {@link
 141.683 +     * java.nio.channels.Selector#wakeup wakeup} method were invoked.
 141.684 +     *
 141.685 +     * <p> If none of the previous conditions hold then this thread's interrupt
 141.686 +     * status will be set. </p>
 141.687 +     *
 141.688 +     * <p> Interrupting a thread that is not alive need not have any effect.
 141.689 +     *
 141.690 +     * @throws  SecurityException
 141.691 +     *          if the current thread cannot modify this thread
 141.692 +     *
 141.693 +     * @revised 6.0
 141.694 +     * @spec JSR-51
 141.695 +     */
 141.696 +    public void interrupt() {
 141.697 +        throw new SecurityException();
 141.698 +    }
 141.699 +
 141.700 +    /**
 141.701 +     * Tests whether the current thread has been interrupted.  The
 141.702 +     * <i>interrupted status</i> of the thread is cleared by this method.  In
 141.703 +     * other words, if this method were to be called twice in succession, the
 141.704 +     * second call would return false (unless the current thread were
 141.705 +     * interrupted again, after the first call had cleared its interrupted
 141.706 +     * status and before the second call had examined it).
 141.707 +     *
 141.708 +     * <p>A thread interruption ignored because a thread was not alive
 141.709 +     * at the time of the interrupt will be reflected by this method
 141.710 +     * returning false.
 141.711 +     *
 141.712 +     * @return  <code>true</code> if the current thread has been interrupted;
 141.713 +     *          <code>false</code> otherwise.
 141.714 +     * @see #isInterrupted()
 141.715 +     * @revised 6.0
 141.716 +     */
 141.717 +    public static boolean interrupted() {
 141.718 +        return currentThread().isInterrupted();
 141.719 +    }
 141.720 +
 141.721 +    /**
 141.722 +     * Tests whether this thread has been interrupted.  The <i>interrupted
 141.723 +     * status</i> of the thread is unaffected by this method.
 141.724 +     *
 141.725 +     * <p>A thread interruption ignored because a thread was not alive
 141.726 +     * at the time of the interrupt will be reflected by this method
 141.727 +     * returning false.
 141.728 +     *
 141.729 +     * @return  <code>true</code> if this thread has been interrupted;
 141.730 +     *          <code>false</code> otherwise.
 141.731 +     * @see     #interrupted()
 141.732 +     * @revised 6.0
 141.733 +     */
 141.734 +    public boolean isInterrupted() {
 141.735 +        return false;
 141.736 +    }
 141.737 +
 141.738 +    /**
 141.739 +     * Throws {@link NoSuchMethodError}.
 141.740 +     *
 141.741 +     * @deprecated This method was originally designed to destroy this
 141.742 +     *     thread without any cleanup. Any monitors it held would have
 141.743 +     *     remained locked. However, the method was never implemented.
 141.744 +     *     If if were to be implemented, it would be deadlock-prone in
 141.745 +     *     much the manner of {@link #suspend}. If the target thread held
 141.746 +     *     a lock protecting a critical system resource when it was
 141.747 +     *     destroyed, no thread could ever access this resource again.
 141.748 +     *     If another thread ever attempted to lock this resource, deadlock
 141.749 +     *     would result. Such deadlocks typically manifest themselves as
 141.750 +     *     "frozen" processes. For more information, see
 141.751 +     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">
 141.752 +     *     Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 141.753 +     * @throws NoSuchMethodError always
 141.754 +     */
 141.755 +    @Deprecated
 141.756 +    public void destroy() {
 141.757 +        throw new SecurityException();
 141.758 +    }
 141.759 +
 141.760 +    /**
 141.761 +     * Tests if this thread is alive. A thread is alive if it has
 141.762 +     * been started and has not yet died.
 141.763 +     *
 141.764 +     * @return  <code>true</code> if this thread is alive;
 141.765 +     *          <code>false</code> otherwise.
 141.766 +     */
 141.767 +    public final boolean isAlive() {
 141.768 +        return true;
 141.769 +    }
 141.770 +
 141.771 +    /**
 141.772 +     * Suspends this thread.
 141.773 +     * <p>
 141.774 +     * First, the <code>checkAccess</code> method of this thread is called
 141.775 +     * with no arguments. This may result in throwing a
 141.776 +     * <code>SecurityException </code>(in the current thread).
 141.777 +     * <p>
 141.778 +     * If the thread is alive, it is suspended and makes no further
 141.779 +     * progress unless and until it is resumed.
 141.780 +     *
 141.781 +     * @exception  SecurityException  if the current thread cannot modify
 141.782 +     *               this thread.
 141.783 +     * @see #checkAccess
 141.784 +     * @deprecated   This method has been deprecated, as it is
 141.785 +     *   inherently deadlock-prone.  If the target thread holds a lock on the
 141.786 +     *   monitor protecting a critical system resource when it is suspended, no
 141.787 +     *   thread can access this resource until the target thread is resumed. If
 141.788 +     *   the thread that would resume the target thread attempts to lock this
 141.789 +     *   monitor prior to calling <code>resume</code>, deadlock results.  Such
 141.790 +     *   deadlocks typically manifest themselves as "frozen" processes.
 141.791 +     *   For more information, see
 141.792 +     *   <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 141.793 +     *   are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 141.794 +     */
 141.795 +    @Deprecated
 141.796 +    public final void suspend() {
 141.797 +        checkAccess();
 141.798 +    }
 141.799 +
 141.800 +    /**
 141.801 +     * Resumes a suspended thread.
 141.802 +     * <p>
 141.803 +     * First, the <code>checkAccess</code> method of this thread is called
 141.804 +     * with no arguments. This may result in throwing a
 141.805 +     * <code>SecurityException</code> (in the current thread).
 141.806 +     * <p>
 141.807 +     * If the thread is alive but suspended, it is resumed and is
 141.808 +     * permitted to make progress in its execution.
 141.809 +     *
 141.810 +     * @exception  SecurityException  if the current thread cannot modify this
 141.811 +     *               thread.
 141.812 +     * @see        #checkAccess
 141.813 +     * @see        #suspend()
 141.814 +     * @deprecated This method exists solely for use with {@link #suspend},
 141.815 +     *     which has been deprecated because it is deadlock-prone.
 141.816 +     *     For more information, see
 141.817 +     *     <a href="{@docRoot}/../technotes/guides/concurrency/threadPrimitiveDeprecation.html">Why
 141.818 +     *     are Thread.stop, Thread.suspend and Thread.resume Deprecated?</a>.
 141.819 +     */
 141.820 +    @Deprecated
 141.821 +    public final void resume() {
 141.822 +        checkAccess();
 141.823 +    }
 141.824 +
 141.825 +    /**
 141.826 +     * Changes the priority of this thread.
 141.827 +     * <p>
 141.828 +     * First the <code>checkAccess</code> method of this thread is called
 141.829 +     * with no arguments. This may result in throwing a
 141.830 +     * <code>SecurityException</code>.
 141.831 +     * <p>
 141.832 +     * Otherwise, the priority of this thread is set to the smaller of
 141.833 +     * the specified <code>newPriority</code> and the maximum permitted
 141.834 +     * priority of the thread's thread group.
 141.835 +     *
 141.836 +     * @param newPriority priority to set this thread to
 141.837 +     * @exception  IllegalArgumentException  If the priority is not in the
 141.838 +     *               range <code>MIN_PRIORITY</code> to
 141.839 +     *               <code>MAX_PRIORITY</code>.
 141.840 +     * @exception  SecurityException  if the current thread cannot modify
 141.841 +     *               this thread.
 141.842 +     * @see        #getPriority
 141.843 +     * @see        #checkAccess()
 141.844 +     * @see        #getThreadGroup()
 141.845 +     * @see        #MAX_PRIORITY
 141.846 +     * @see        #MIN_PRIORITY
 141.847 +     * @see        ThreadGroup#getMaxPriority()
 141.848 +     */
 141.849 +    public final void setPriority(int newPriority) {
 141.850 +        throw new SecurityException();
 141.851 +    }
 141.852 +
 141.853 +    /**
 141.854 +     * Returns this thread's priority.
 141.855 +     *
 141.856 +     * @return  this thread's priority.
 141.857 +     * @see     #setPriority
 141.858 +     */
 141.859 +    public final int getPriority() {
 141.860 +        return Thread.NORM_PRIORITY;
 141.861 +    }
 141.862 +
 141.863 +    /**
 141.864 +     * Changes the name of this thread to be equal to the argument
 141.865 +     * <code>name</code>.
 141.866 +     * <p>
 141.867 +     * First the <code>checkAccess</code> method of this thread is called
 141.868 +     * with no arguments. This may result in throwing a
 141.869 +     * <code>SecurityException</code>.
 141.870 +     *
 141.871 +     * @param      name   the new name for this thread.
 141.872 +     * @exception  SecurityException  if the current thread cannot modify this
 141.873 +     *               thread.
 141.874 +     * @see        #getName
 141.875 +     * @see        #checkAccess()
 141.876 +     */
 141.877 +    public final void setName(String name) {
 141.878 +        throw new SecurityException();
 141.879 +    }
 141.880 +
 141.881 +    /**
 141.882 +     * Returns this thread's name.
 141.883 +     *
 141.884 +     * @return  this thread's name.
 141.885 +     * @see     #setName(String)
 141.886 +     */
 141.887 +    public final String getName() {
 141.888 +        return String.valueOf(name);
 141.889 +    }
 141.890 +
 141.891 +    /**
 141.892 +     * Returns the thread group to which this thread belongs.
 141.893 +     * This method returns null if this thread has died
 141.894 +     * (been stopped).
 141.895 +     *
 141.896 +     * @return  this thread's thread group.
 141.897 +     */
 141.898 +//    public final ThreadGroup getThreadGroup() {
 141.899 +//        return group;
 141.900 +//    }
 141.901 +
 141.902 +    /**
 141.903 +     * Returns an estimate of the number of active threads in the current
 141.904 +     * thread's {@linkplain java.lang.ThreadGroup thread group} and its
 141.905 +     * subgroups. Recursively iterates over all subgroups in the current
 141.906 +     * thread's thread group.
 141.907 +     *
 141.908 +     * <p> The value returned is only an estimate because the number of
 141.909 +     * threads may change dynamically while this method traverses internal
 141.910 +     * data structures, and might be affected by the presence of certain
 141.911 +     * system threads. This method is intended primarily for debugging
 141.912 +     * and monitoring purposes.
 141.913 +     *
 141.914 +     * @return  an estimate of the number of active threads in the current
 141.915 +     *          thread's thread group and in any other thread group that
 141.916 +     *          has the current thread's thread group as an ancestor
 141.917 +     */
 141.918 +    public static int activeCount() {
 141.919 +        return 1;
 141.920 +    }
 141.921 +
 141.922 +    /**
 141.923 +     * Copies into the specified array every active thread in the current
 141.924 +     * thread's thread group and its subgroups. This method simply
 141.925 +     * invokes the {@link java.lang.ThreadGroup#enumerate(Thread[])}
 141.926 +     * method of the current thread's thread group.
 141.927 +     *
 141.928 +     * <p> An application might use the {@linkplain #activeCount activeCount}
 141.929 +     * method to get an estimate of how big the array should be, however
 141.930 +     * <i>if the array is too short to hold all the threads, the extra threads
 141.931 +     * are silently ignored.</i>  If it is critical to obtain every active
 141.932 +     * thread in the current thread's thread group and its subgroups, the
 141.933 +     * invoker should verify that the returned int value is strictly less
 141.934 +     * than the length of {@code tarray}.
 141.935 +     *
 141.936 +     * <p> Due to the inherent race condition in this method, it is recommended
 141.937 +     * that the method only be used for debugging and monitoring purposes.
 141.938 +     *
 141.939 +     * @param  tarray
 141.940 +     *         an array into which to put the list of threads
 141.941 +     *
 141.942 +     * @return  the number of threads put into the array
 141.943 +     *
 141.944 +     * @throws  SecurityException
 141.945 +     *          if {@link java.lang.ThreadGroup#checkAccess} determines that
 141.946 +     *          the current thread cannot access its thread group
 141.947 +     */
 141.948 +    public static int enumerate(Thread tarray[]) {
 141.949 +        throw new SecurityException();
 141.950 +    }
 141.951 +
 141.952 +    /**
 141.953 +     * Counts the number of stack frames in this thread. The thread must
 141.954 +     * be suspended.
 141.955 +     *
 141.956 +     * @return     the number of stack frames in this thread.
 141.957 +     * @exception  IllegalThreadStateException  if this thread is not
 141.958 +     *             suspended.
 141.959 +     * @deprecated The definition of this call depends on {@link #suspend},
 141.960 +     *             which is deprecated.  Further, the results of this call
 141.961 +     *             were never well-defined.
 141.962 +     */
 141.963 +    @Deprecated
 141.964 +    public native int countStackFrames();
 141.965 +
 141.966 +    /**
 141.967 +     * Waits at most {@code millis} milliseconds for this thread to
 141.968 +     * die. A timeout of {@code 0} means to wait forever.
 141.969 +     *
 141.970 +     * <p> This implementation uses a loop of {@code this.wait} calls
 141.971 +     * conditioned on {@code this.isAlive}. As a thread terminates the
 141.972 +     * {@code this.notifyAll} method is invoked. It is recommended that
 141.973 +     * applications not use {@code wait}, {@code notify}, or
 141.974 +     * {@code notifyAll} on {@code Thread} instances.
 141.975 +     *
 141.976 +     * @param  millis
 141.977 +     *         the time to wait in milliseconds
 141.978 +     *
 141.979 +     * @throws  IllegalArgumentException
 141.980 +     *          if the value of {@code millis} is negative
 141.981 +     *
 141.982 +     * @throws  InterruptedException
 141.983 +     *          if any thread has interrupted the current thread. The
 141.984 +     *          <i>interrupted status</i> of the current thread is
 141.985 +     *          cleared when this exception is thrown.
 141.986 +     */
 141.987 +    public final synchronized void join(long millis)
 141.988 +    throws InterruptedException {
 141.989 +        long base = System.currentTimeMillis();
 141.990 +        long now = 0;
 141.991 +
 141.992 +        if (millis < 0) {
 141.993 +            throw new IllegalArgumentException("timeout value is negative");
 141.994 +        }
 141.995 +
 141.996 +        if (millis == 0) {
 141.997 +            while (isAlive()) {
 141.998 +                wait(0);
 141.999 +            }
141.1000 +        } else {
141.1001 +            while (isAlive()) {
141.1002 +                long delay = millis - now;
141.1003 +                if (delay <= 0) {
141.1004 +                    break;
141.1005 +                }
141.1006 +                wait(delay);
141.1007 +                now = System.currentTimeMillis() - base;
141.1008 +            }
141.1009 +        }
141.1010 +    }
141.1011 +
141.1012 +    /**
141.1013 +     * Waits at most {@code millis} milliseconds plus
141.1014 +     * {@code nanos} nanoseconds for this thread to die.
141.1015 +     *
141.1016 +     * <p> This implementation uses a loop of {@code this.wait} calls
141.1017 +     * conditioned on {@code this.isAlive}. As a thread terminates the
141.1018 +     * {@code this.notifyAll} method is invoked. It is recommended that
141.1019 +     * applications not use {@code wait}, {@code notify}, or
141.1020 +     * {@code notifyAll} on {@code Thread} instances.
141.1021 +     *
141.1022 +     * @param  millis
141.1023 +     *         the time to wait in milliseconds
141.1024 +     *
141.1025 +     * @param  nanos
141.1026 +     *         {@code 0-999999} additional nanoseconds to wait
141.1027 +     *
141.1028 +     * @throws  IllegalArgumentException
141.1029 +     *          if the value of {@code millis} is negative, or the value
141.1030 +     *          of {@code nanos} is not in the range {@code 0-999999}
141.1031 +     *
141.1032 +     * @throws  InterruptedException
141.1033 +     *          if any thread has interrupted the current thread. The
141.1034 +     *          <i>interrupted status</i> of the current thread is
141.1035 +     *          cleared when this exception is thrown.
141.1036 +     */
141.1037 +    public final synchronized void join(long millis, int nanos)
141.1038 +    throws InterruptedException {
141.1039 +
141.1040 +        if (millis < 0) {
141.1041 +            throw new IllegalArgumentException("timeout value is negative");
141.1042 +        }
141.1043 +
141.1044 +        if (nanos < 0 || nanos > 999999) {
141.1045 +            throw new IllegalArgumentException(
141.1046 +                                "nanosecond timeout value out of range");
141.1047 +        }
141.1048 +
141.1049 +        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
141.1050 +            millis++;
141.1051 +        }
141.1052 +
141.1053 +        join(millis);
141.1054 +    }
141.1055 +
141.1056 +    /**
141.1057 +     * Waits for this thread to die.
141.1058 +     *
141.1059 +     * <p> An invocation of this method behaves in exactly the same
141.1060 +     * way as the invocation
141.1061 +     *
141.1062 +     * <blockquote>
141.1063 +     * {@linkplain #join(long) join}{@code (0)}
141.1064 +     * </blockquote>
141.1065 +     *
141.1066 +     * @throws  InterruptedException
141.1067 +     *          if any thread has interrupted the current thread. The
141.1068 +     *          <i>interrupted status</i> of the current thread is
141.1069 +     *          cleared when this exception is thrown.
141.1070 +     */
141.1071 +    public final void join() throws InterruptedException {
141.1072 +        join(0);
141.1073 +    }
141.1074 +
141.1075 +    /**
141.1076 +     * Prints a stack trace of the current thread to the standard error stream.
141.1077 +     * This method is used only for debugging.
141.1078 +     *
141.1079 +     * @see     Throwable#printStackTrace()
141.1080 +     */
141.1081 +    public static void dumpStack() {
141.1082 +        new Exception("Stack trace").printStackTrace();
141.1083 +    }
141.1084 +
141.1085 +    /**
141.1086 +     * Marks this thread as either a {@linkplain #isDaemon daemon} thread
141.1087 +     * or a user thread. The Java Virtual Machine exits when the only
141.1088 +     * threads running are all daemon threads.
141.1089 +     *
141.1090 +     * <p> This method must be invoked before the thread is started.
141.1091 +     *
141.1092 +     * @param  on
141.1093 +     *         if {@code true}, marks this thread as a daemon thread
141.1094 +     *
141.1095 +     * @throws  IllegalThreadStateException
141.1096 +     *          if this thread is {@linkplain #isAlive alive}
141.1097 +     *
141.1098 +     * @throws  SecurityException
141.1099 +     *          if {@link #checkAccess} determines that the current
141.1100 +     *          thread cannot modify this thread
141.1101 +     */
141.1102 +    public final void setDaemon(boolean on) {
141.1103 +        throw new SecurityException();
141.1104 +    }
141.1105 +
141.1106 +    /**
141.1107 +     * Tests if this thread is a daemon thread.
141.1108 +     *
141.1109 +     * @return  <code>true</code> if this thread is a daemon thread;
141.1110 +     *          <code>false</code> otherwise.
141.1111 +     * @see     #setDaemon(boolean)
141.1112 +     */
141.1113 +    public final boolean isDaemon() {
141.1114 +        return false;
141.1115 +    }
141.1116 +
141.1117 +    /**
141.1118 +     * Determines if the currently running thread has permission to
141.1119 +     * modify this thread.
141.1120 +     * <p>
141.1121 +     * If there is a security manager, its <code>checkAccess</code> method
141.1122 +     * is called with this thread as its argument. This may result in
141.1123 +     * throwing a <code>SecurityException</code>.
141.1124 +     *
141.1125 +     * @exception  SecurityException  if the current thread is not allowed to
141.1126 +     *               access this thread.
141.1127 +     * @see        SecurityManager#checkAccess(Thread)
141.1128 +     */
141.1129 +    public final void checkAccess() {
141.1130 +        throw new SecurityException();
141.1131 +    }
141.1132 +
141.1133 +    /**
141.1134 +     * Returns a string representation of this thread, including the
141.1135 +     * thread's name, priority, and thread group.
141.1136 +     *
141.1137 +     * @return  a string representation of this thread.
141.1138 +     */
141.1139 +    public String toString() {
141.1140 +        return "Thread[" + getName() + "," + getPriority() + "," +
141.1141 +                        "" + "]";
141.1142 +    }
141.1143 +
141.1144 +    /**
141.1145 +     * Returns the context ClassLoader for this Thread. The context
141.1146 +     * ClassLoader is provided by the creator of the thread for use
141.1147 +     * by code running in this thread when loading classes and resources.
141.1148 +     * If not {@linkplain #setContextClassLoader set}, the default is the
141.1149 +     * ClassLoader context of the parent Thread. The context ClassLoader of the
141.1150 +     * primordial thread is typically set to the class loader used to load the
141.1151 +     * application.
141.1152 +     *
141.1153 +     * <p>If a security manager is present, and the invoker's class loader is not
141.1154 +     * {@code null} and is not the same as or an ancestor of the context class
141.1155 +     * loader, then this method invokes the security manager's {@link
141.1156 +     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
141.1157 +     * method with a {@link RuntimePermission RuntimePermission}{@code
141.1158 +     * ("getClassLoader")} permission to verify that retrieval of the context
141.1159 +     * class loader is permitted.
141.1160 +     *
141.1161 +     * @return  the context ClassLoader for this Thread, or {@code null}
141.1162 +     *          indicating the system class loader (or, failing that, the
141.1163 +     *          bootstrap class loader)
141.1164 +     *
141.1165 +     * @throws  SecurityException
141.1166 +     *          if the current thread cannot get the context ClassLoader
141.1167 +     *
141.1168 +     * @since 1.2
141.1169 +     */
141.1170 +    public ClassLoader getContextClassLoader() {
141.1171 +        return null;
141.1172 +    }
141.1173 +
141.1174 +    /**
141.1175 +     * Sets the context ClassLoader for this Thread. The context
141.1176 +     * ClassLoader can be set when a thread is created, and allows
141.1177 +     * the creator of the thread to provide the appropriate class loader,
141.1178 +     * through {@code getContextClassLoader}, to code running in the thread
141.1179 +     * when loading classes and resources.
141.1180 +     *
141.1181 +     * <p>If a security manager is present, its {@link
141.1182 +     * SecurityManager#checkPermission(java.security.Permission) checkPermission}
141.1183 +     * method is invoked with a {@link RuntimePermission RuntimePermission}{@code
141.1184 +     * ("setContextClassLoader")} permission to see if setting the context
141.1185 +     * ClassLoader is permitted.
141.1186 +     *
141.1187 +     * @param  cl
141.1188 +     *         the context ClassLoader for this Thread, or null  indicating the
141.1189 +     *         system class loader (or, failing that, the bootstrap class loader)
141.1190 +     *
141.1191 +     * @throws  SecurityException
141.1192 +     *          if the current thread cannot set the context ClassLoader
141.1193 +     *
141.1194 +     * @since 1.2
141.1195 +     */
141.1196 +    public void setContextClassLoader(ClassLoader cl) {
141.1197 +        throw new SecurityException();
141.1198 +    }
141.1199 +
141.1200 +    /**
141.1201 +     * Returns <tt>true</tt> if and only if the current thread holds the
141.1202 +     * monitor lock on the specified object.
141.1203 +     *
141.1204 +     * <p>This method is designed to allow a program to assert that
141.1205 +     * the current thread already holds a specified lock:
141.1206 +     * <pre>
141.1207 +     *     assert Thread.holdsLock(obj);
141.1208 +     * </pre>
141.1209 +     *
141.1210 +     * @param  obj the object on which to test lock ownership
141.1211 +     * @throws NullPointerException if obj is <tt>null</tt>
141.1212 +     * @return <tt>true</tt> if the current thread holds the monitor lock on
141.1213 +     *         the specified object.
141.1214 +     * @since 1.4
141.1215 +     */
141.1216 +    public static boolean holdsLock(Object obj) {
141.1217 +        return true;
141.1218 +    }
141.1219 +
141.1220 +    /**
141.1221 +     * Returns an array of stack trace elements representing the stack dump
141.1222 +     * of this thread.  This method will return a zero-length array if
141.1223 +     * this thread has not started, has started but has not yet been
141.1224 +     * scheduled to run by the system, or has terminated.
141.1225 +     * If the returned array is of non-zero length then the first element of
141.1226 +     * the array represents the top of the stack, which is the most recent
141.1227 +     * method invocation in the sequence.  The last element of the array
141.1228 +     * represents the bottom of the stack, which is the least recent method
141.1229 +     * invocation in the sequence.
141.1230 +     *
141.1231 +     * <p>If there is a security manager, and this thread is not
141.1232 +     * the current thread, then the security manager's
141.1233 +     * <tt>checkPermission</tt> method is called with a
141.1234 +     * <tt>RuntimePermission("getStackTrace")</tt> permission
141.1235 +     * to see if it's ok to get the stack trace.
141.1236 +     *
141.1237 +     * <p>Some virtual machines may, under some circumstances, omit one
141.1238 +     * or more stack frames from the stack trace.  In the extreme case,
141.1239 +     * a virtual machine that has no stack trace information concerning
141.1240 +     * this thread is permitted to return a zero-length array from this
141.1241 +     * method.
141.1242 +     *
141.1243 +     * @return an array of <tt>StackTraceElement</tt>,
141.1244 +     * each represents one stack frame.
141.1245 +     *
141.1246 +     * @throws SecurityException
141.1247 +     *        if a security manager exists and its
141.1248 +     *        <tt>checkPermission</tt> method doesn't allow
141.1249 +     *        getting the stack trace of thread.
141.1250 +     * @see SecurityManager#checkPermission
141.1251 +     * @see RuntimePermission
141.1252 +     * @see Throwable#getStackTrace
141.1253 +     *
141.1254 +     * @since 1.5
141.1255 +     */
141.1256 +    public StackTraceElement[] getStackTrace() {
141.1257 +        throw new SecurityException();
141.1258 +    }
141.1259 +
141.1260 +    /**
141.1261 +     * Returns a map of stack traces for all live threads.
141.1262 +     * The map keys are threads and each map value is an array of
141.1263 +     * <tt>StackTraceElement</tt> that represents the stack dump
141.1264 +     * of the corresponding <tt>Thread</tt>.
141.1265 +     * The returned stack traces are in the format specified for
141.1266 +     * the {@link #getStackTrace getStackTrace} method.
141.1267 +     *
141.1268 +     * <p>The threads may be executing while this method is called.
141.1269 +     * The stack trace of each thread only represents a snapshot and
141.1270 +     * each stack trace may be obtained at different time.  A zero-length
141.1271 +     * array will be returned in the map value if the virtual machine has
141.1272 +     * no stack trace information about a thread.
141.1273 +     *
141.1274 +     * <p>If there is a security manager, then the security manager's
141.1275 +     * <tt>checkPermission</tt> method is called with a
141.1276 +     * <tt>RuntimePermission("getStackTrace")</tt> permission as well as
141.1277 +     * <tt>RuntimePermission("modifyThreadGroup")</tt> permission
141.1278 +     * to see if it is ok to get the stack trace of all threads.
141.1279 +     *
141.1280 +     * @return a <tt>Map</tt> from <tt>Thread</tt> to an array of
141.1281 +     * <tt>StackTraceElement</tt> that represents the stack trace of
141.1282 +     * the corresponding thread.
141.1283 +     *
141.1284 +     * @throws SecurityException
141.1285 +     *        if a security manager exists and its
141.1286 +     *        <tt>checkPermission</tt> method doesn't allow
141.1287 +     *        getting the stack trace of thread.
141.1288 +     * @see #getStackTrace
141.1289 +     * @see SecurityManager#checkPermission
141.1290 +     * @see RuntimePermission
141.1291 +     * @see Throwable#getStackTrace
141.1292 +     *
141.1293 +     * @since 1.5
141.1294 +     */
141.1295 +    public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
141.1296 +        throw new SecurityException();
141.1297 +    }
141.1298 +
141.1299 +    /**
141.1300 +     * Returns the identifier of this Thread.  The thread ID is a positive
141.1301 +     * <tt>long</tt> number generated when this thread was created.
141.1302 +     * The thread ID is unique and remains unchanged during its lifetime.
141.1303 +     * When a thread is terminated, this thread ID may be reused.
141.1304 +     *
141.1305 +     * @return this thread's ID.
141.1306 +     * @since 1.5
141.1307 +     */
141.1308 +    public long getId() {
141.1309 +        return 0;
141.1310 +    }
141.1311 +
141.1312 +    /**
141.1313 +     * A thread state.  A thread can be in one of the following states:
141.1314 +     * <ul>
141.1315 +     * <li>{@link #NEW}<br>
141.1316 +     *     A thread that has not yet started is in this state.
141.1317 +     *     </li>
141.1318 +     * <li>{@link #RUNNABLE}<br>
141.1319 +     *     A thread executing in the Java virtual machine is in this state.
141.1320 +     *     </li>
141.1321 +     * <li>{@link #BLOCKED}<br>
141.1322 +     *     A thread that is blocked waiting for a monitor lock
141.1323 +     *     is in this state.
141.1324 +     *     </li>
141.1325 +     * <li>{@link #WAITING}<br>
141.1326 +     *     A thread that is waiting indefinitely for another thread to
141.1327 +     *     perform a particular action is in this state.
141.1328 +     *     </li>
141.1329 +     * <li>{@link #TIMED_WAITING}<br>
141.1330 +     *     A thread that is waiting for another thread to perform an action
141.1331 +     *     for up to a specified waiting time is in this state.
141.1332 +     *     </li>
141.1333 +     * <li>{@link #TERMINATED}<br>
141.1334 +     *     A thread that has exited is in this state.
141.1335 +     *     </li>
141.1336 +     * </ul>
141.1337 +     *
141.1338 +     * <p>
141.1339 +     * A thread can be in only one state at a given point in time.
141.1340 +     * These states are virtual machine states which do not reflect
141.1341 +     * any operating system thread states.
141.1342 +     *
141.1343 +     * @since   1.5
141.1344 +     * @see #getState
141.1345 +     */
141.1346 +    public enum State {
141.1347 +        /**
141.1348 +         * Thread state for a thread which has not yet started.
141.1349 +         */
141.1350 +        NEW,
141.1351 +
141.1352 +        /**
141.1353 +         * Thread state for a runnable thread.  A thread in the runnable
141.1354 +         * state is executing in the Java virtual machine but it may
141.1355 +         * be waiting for other resources from the operating system
141.1356 +         * such as processor.
141.1357 +         */
141.1358 +        RUNNABLE,
141.1359 +
141.1360 +        /**
141.1361 +         * Thread state for a thread blocked waiting for a monitor lock.
141.1362 +         * A thread in the blocked state is waiting for a monitor lock
141.1363 +         * to enter a synchronized block/method or
141.1364 +         * reenter a synchronized block/method after calling
141.1365 +         * {@link Object#wait() Object.wait}.
141.1366 +         */
141.1367 +        BLOCKED,
141.1368 +
141.1369 +        /**
141.1370 +         * Thread state for a waiting thread.
141.1371 +         * A thread is in the waiting state due to calling one of the
141.1372 +         * following methods:
141.1373 +         * <ul>
141.1374 +         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
141.1375 +         *   <li>{@link #join() Thread.join} with no timeout</li>
141.1376 +         *   <li>{@link LockSupport#park() LockSupport.park}</li>
141.1377 +         * </ul>
141.1378 +         *
141.1379 +         * <p>A thread in the waiting state is waiting for another thread to
141.1380 +         * perform a particular action.
141.1381 +         *
141.1382 +         * For example, a thread that has called <tt>Object.wait()</tt>
141.1383 +         * on an object is waiting for another thread to call
141.1384 +         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
141.1385 +         * that object. A thread that has called <tt>Thread.join()</tt>
141.1386 +         * is waiting for a specified thread to terminate.
141.1387 +         */
141.1388 +        WAITING,
141.1389 +
141.1390 +        /**
141.1391 +         * Thread state for a waiting thread with a specified waiting time.
141.1392 +         * A thread is in the timed waiting state due to calling one of
141.1393 +         * the following methods with a specified positive waiting time:
141.1394 +         * <ul>
141.1395 +         *   <li>{@link #sleep Thread.sleep}</li>
141.1396 +         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
141.1397 +         *   <li>{@link #join(long) Thread.join} with timeout</li>
141.1398 +         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
141.1399 +         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
141.1400 +         * </ul>
141.1401 +         */
141.1402 +        TIMED_WAITING,
141.1403 +
141.1404 +        /**
141.1405 +         * Thread state for a terminated thread.
141.1406 +         * The thread has completed execution.
141.1407 +         */
141.1408 +        TERMINATED;
141.1409 +    }
141.1410 +
141.1411 +    /**
141.1412 +     * Returns the state of this thread.
141.1413 +     * This method is designed for use in monitoring of the system state,
141.1414 +     * not for synchronization control.
141.1415 +     *
141.1416 +     * @return this thread's state.
141.1417 +     * @since 1.5
141.1418 +     */
141.1419 +    public State getState() {
141.1420 +        // get current thread state
141.1421 +        return State.RUNNABLE;
141.1422 +    }
141.1423 +
141.1424 +    // Added in JSR-166
141.1425 +
141.1426 +    /**
141.1427 +     * Interface for handlers invoked when a <tt>Thread</tt> abruptly
141.1428 +     * terminates due to an uncaught exception.
141.1429 +     * <p>When a thread is about to terminate due to an uncaught exception
141.1430 +     * the Java Virtual Machine will query the thread for its
141.1431 +     * <tt>UncaughtExceptionHandler</tt> using
141.1432 +     * {@link #getUncaughtExceptionHandler} and will invoke the handler's
141.1433 +     * <tt>uncaughtException</tt> method, passing the thread and the
141.1434 +     * exception as arguments.
141.1435 +     * If a thread has not had its <tt>UncaughtExceptionHandler</tt>
141.1436 +     * explicitly set, then its <tt>ThreadGroup</tt> object acts as its
141.1437 +     * <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
141.1438 +     * has no
141.1439 +     * special requirements for dealing with the exception, it can forward
141.1440 +     * the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
141.1441 +     * default uncaught exception handler}.
141.1442 +     *
141.1443 +     * @see #setDefaultUncaughtExceptionHandler
141.1444 +     * @see #setUncaughtExceptionHandler
141.1445 +     * @see ThreadGroup#uncaughtException
141.1446 +     * @since 1.5
141.1447 +     */
141.1448 +    public interface UncaughtExceptionHandler {
141.1449 +        /**
141.1450 +         * Method invoked when the given thread terminates due to the
141.1451 +         * given uncaught exception.
141.1452 +         * <p>Any exception thrown by this method will be ignored by the
141.1453 +         * Java Virtual Machine.
141.1454 +         * @param t the thread
141.1455 +         * @param e the exception
141.1456 +         */
141.1457 +        void uncaughtException(Thread t, Throwable e);
141.1458 +    }
141.1459 +
141.1460 +    // null unless explicitly set
141.1461 +    private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
141.1462 +
141.1463 +    // null unless explicitly set
141.1464 +    private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
141.1465 +
141.1466 +    /**
141.1467 +     * Set the default handler invoked when a thread abruptly terminates
141.1468 +     * due to an uncaught exception, and no other handler has been defined
141.1469 +     * for that thread.
141.1470 +     *
141.1471 +     * <p>Uncaught exception handling is controlled first by the thread, then
141.1472 +     * by the thread's {@link ThreadGroup} object and finally by the default
141.1473 +     * uncaught exception handler. If the thread does not have an explicit
141.1474 +     * uncaught exception handler set, and the thread's thread group
141.1475 +     * (including parent thread groups)  does not specialize its
141.1476 +     * <tt>uncaughtException</tt> method, then the default handler's
141.1477 +     * <tt>uncaughtException</tt> method will be invoked.
141.1478 +     * <p>By setting the default uncaught exception handler, an application
141.1479 +     * can change the way in which uncaught exceptions are handled (such as
141.1480 +     * logging to a specific device, or file) for those threads that would
141.1481 +     * already accept whatever &quot;default&quot; behavior the system
141.1482 +     * provided.
141.1483 +     *
141.1484 +     * <p>Note that the default uncaught exception handler should not usually
141.1485 +     * defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
141.1486 +     * infinite recursion.
141.1487 +     *
141.1488 +     * @param eh the object to use as the default uncaught exception handler.
141.1489 +     * If <tt>null</tt> then there is no default handler.
141.1490 +     *
141.1491 +     * @throws SecurityException if a security manager is present and it
141.1492 +     *         denies <tt>{@link RuntimePermission}
141.1493 +     *         (&quot;setDefaultUncaughtExceptionHandler&quot;)</tt>
141.1494 +     *
141.1495 +     * @see #setUncaughtExceptionHandler
141.1496 +     * @see #getUncaughtExceptionHandler
141.1497 +     * @see ThreadGroup#uncaughtException
141.1498 +     * @since 1.5
141.1499 +     */
141.1500 +    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
141.1501 +        throw new SecurityException();
141.1502 +    }
141.1503 +
141.1504 +    /**
141.1505 +     * Returns the default handler invoked when a thread abruptly terminates
141.1506 +     * due to an uncaught exception. If the returned value is <tt>null</tt>,
141.1507 +     * there is no default.
141.1508 +     * @since 1.5
141.1509 +     * @see #setDefaultUncaughtExceptionHandler
141.1510 +     */
141.1511 +    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
141.1512 +        return defaultUncaughtExceptionHandler;
141.1513 +    }
141.1514 +
141.1515 +    /**
141.1516 +     * Returns the handler invoked when this thread abruptly terminates
141.1517 +     * due to an uncaught exception. If this thread has not had an
141.1518 +     * uncaught exception handler explicitly set then this thread's
141.1519 +     * <tt>ThreadGroup</tt> object is returned, unless this thread
141.1520 +     * has terminated, in which case <tt>null</tt> is returned.
141.1521 +     * @since 1.5
141.1522 +     */
141.1523 +    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
141.1524 +        return uncaughtExceptionHandler != null ?
141.1525 +            uncaughtExceptionHandler : null;
141.1526 +    }
141.1527 +
141.1528 +    /**
141.1529 +     * Set the handler invoked when this thread abruptly terminates
141.1530 +     * due to an uncaught exception.
141.1531 +     * <p>A thread can take full control of how it responds to uncaught
141.1532 +     * exceptions by having its uncaught exception handler explicitly set.
141.1533 +     * If no such handler is set then the thread's <tt>ThreadGroup</tt>
141.1534 +     * object acts as its handler.
141.1535 +     * @param eh the object to use as this thread's uncaught exception
141.1536 +     * handler. If <tt>null</tt> then this thread has no explicit handler.
141.1537 +     * @throws  SecurityException  if the current thread is not allowed to
141.1538 +     *          modify this thread.
141.1539 +     * @see #setDefaultUncaughtExceptionHandler
141.1540 +     * @see ThreadGroup#uncaughtException
141.1541 +     * @since 1.5
141.1542 +     */
141.1543 +    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
141.1544 +        checkAccess();
141.1545 +        uncaughtExceptionHandler = eh;
141.1546 +    }
141.1547 +}
   142.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   142.2 +++ b/rt/emul/compact/src/main/java/java/lang/ThreadLocal.java	Mon Oct 07 14:20:58 2013 +0200
   142.3 @@ -0,0 +1,157 @@
   142.4 +/*
   142.5 + * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
   142.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   142.7 + *
   142.8 + * This code is free software; you can redistribute it and/or modify it
   142.9 + * under the terms of the GNU General Public License version 2 only, as
  142.10 + * published by the Free Software Foundation.  Oracle designates this
  142.11 + * particular file as subject to the "Classpath" exception as provided
  142.12 + * by Oracle in the LICENSE file that accompanied this code.
  142.13 + *
  142.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  142.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  142.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  142.17 + * version 2 for more details (a copy is included in the LICENSE file that
  142.18 + * accompanied this code).
  142.19 + *
  142.20 + * You should have received a copy of the GNU General Public License version
  142.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  142.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  142.23 + *
  142.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  142.25 + * or visit www.oracle.com if you need additional information or have any
  142.26 + * questions.
  142.27 + */
  142.28 +
  142.29 +package java.lang;
  142.30 +
  142.31 +/**
  142.32 + * This class provides thread-local variables.  These variables differ from
  142.33 + * their normal counterparts in that each thread that accesses one (via its
  142.34 + * <tt>get</tt> or <tt>set</tt> method) has its own, independently initialized
  142.35 + * copy of the variable.  <tt>ThreadLocal</tt> instances are typically private
  142.36 + * static fields in classes that wish to associate state with a thread (e.g.,
  142.37 + * a user ID or Transaction ID).
  142.38 + *
  142.39 + * <p>For example, the class below generates unique identifiers local to each
  142.40 + * thread.
  142.41 + * A thread's id is assigned the first time it invokes <tt>ThreadId.get()</tt>
  142.42 + * and remains unchanged on subsequent calls.
  142.43 + * <pre>
  142.44 + * import java.util.concurrent.atomic.AtomicInteger;
  142.45 + *
  142.46 + * public class ThreadId {
  142.47 + *     // Atomic integer containing the next thread ID to be assigned
  142.48 + *     private static final AtomicInteger nextId = new AtomicInteger(0);
  142.49 + *
  142.50 + *     // Thread local variable containing each thread's ID
  142.51 + *     private static final ThreadLocal&lt;Integer> threadId =
  142.52 + *         new ThreadLocal&lt;Integer>() {
  142.53 + *             &#64;Override protected Integer initialValue() {
  142.54 + *                 return nextId.getAndIncrement();
  142.55 + *         }
  142.56 + *     };
  142.57 + *
  142.58 + *     // Returns the current thread's unique ID, assigning it if necessary
  142.59 + *     public static int get() {
  142.60 + *         return threadId.get();
  142.61 + *     }
  142.62 + * }
  142.63 + * </pre>
  142.64 + * <p>Each thread holds an implicit reference to its copy of a thread-local
  142.65 + * variable as long as the thread is alive and the <tt>ThreadLocal</tt>
  142.66 + * instance is accessible; after a thread goes away, all of its copies of
  142.67 + * thread-local instances are subject to garbage collection (unless other
  142.68 + * references to these copies exist).
  142.69 + *
  142.70 + * @author  Josh Bloch and Doug Lea
  142.71 + * @since   1.2
  142.72 + */
  142.73 +public class ThreadLocal<T> {
  142.74 +    private static final Object NONE = new Object();
  142.75 +    private Object value = NONE;
  142.76 +    
  142.77 +    /**
  142.78 +     * Returns the current thread's "initial value" for this
  142.79 +     * thread-local variable.  This method will be invoked the first
  142.80 +     * time a thread accesses the variable with the {@link #get}
  142.81 +     * method, unless the thread previously invoked the {@link #set}
  142.82 +     * method, in which case the <tt>initialValue</tt> method will not
  142.83 +     * be invoked for the thread.  Normally, this method is invoked at
  142.84 +     * most once per thread, but it may be invoked again in case of
  142.85 +     * subsequent invocations of {@link #remove} followed by {@link #get}.
  142.86 +     *
  142.87 +     * <p>This implementation simply returns <tt>null</tt>; if the
  142.88 +     * programmer desires thread-local variables to have an initial
  142.89 +     * value other than <tt>null</tt>, <tt>ThreadLocal</tt> must be
  142.90 +     * subclassed, and this method overridden.  Typically, an
  142.91 +     * anonymous inner class will be used.
  142.92 +     *
  142.93 +     * @return the initial value for this thread-local
  142.94 +     */
  142.95 +    protected T initialValue() {
  142.96 +        return null;
  142.97 +    }
  142.98 +
  142.99 +    /**
 142.100 +     * Creates a thread local variable.
 142.101 +     */
 142.102 +    public ThreadLocal() {
 142.103 +    }
 142.104 +
 142.105 +    /**
 142.106 +     * Returns the value in the current thread's copy of this
 142.107 +     * thread-local variable.  If the variable has no value for the
 142.108 +     * current thread, it is first initialized to the value returned
 142.109 +     * by an invocation of the {@link #initialValue} method.
 142.110 +     *
 142.111 +     * @return the current thread's value of this thread-local
 142.112 +     */
 142.113 +    public T get() {
 142.114 +        if (value == NONE) {
 142.115 +            return setInitialValue();
 142.116 +        } else {
 142.117 +            return (T)value;
 142.118 +        }
 142.119 +    }
 142.120 +
 142.121 +    /**
 142.122 +     * Variant of set() to establish initialValue. Used instead
 142.123 +     * of set() in case user has overridden the set() method.
 142.124 +     *
 142.125 +     * @return the initial value
 142.126 +     */
 142.127 +    private T setInitialValue() {
 142.128 +        T v = initialValue();
 142.129 +        this.value = v;
 142.130 +        return v;
 142.131 +    }
 142.132 +
 142.133 +    /**
 142.134 +     * Sets the current thread's copy of this thread-local variable
 142.135 +     * to the specified value.  Most subclasses will have no need to
 142.136 +     * override this method, relying solely on the {@link #initialValue}
 142.137 +     * method to set the values of thread-locals.
 142.138 +     *
 142.139 +     * @param value the value to be stored in the current thread's copy of
 142.140 +     *        this thread-local.
 142.141 +     */
 142.142 +    public void set(T value) {
 142.143 +        this.value = value;
 142.144 +    }
 142.145 +
 142.146 +    /**
 142.147 +     * Removes the current thread's value for this thread-local
 142.148 +     * variable.  If this thread-local variable is subsequently
 142.149 +     * {@linkplain #get read} by the current thread, its value will be
 142.150 +     * reinitialized by invoking its {@link #initialValue} method,
 142.151 +     * unless its value is {@linkplain #set set} by the current thread
 142.152 +     * in the interim.  This may result in multiple invocations of the
 142.153 +     * <tt>initialValue</tt> method in the current thread.
 142.154 +     *
 142.155 +     * @since 1.5
 142.156 +     */
 142.157 +     public void remove() {
 142.158 +         this.value = NONE;
 142.159 +     }
 142.160 +}
   143.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   143.2 +++ b/rt/emul/compact/src/main/java/java/math/BigDecimal.java	Mon Oct 07 14:20:58 2013 +0200
   143.3 @@ -0,0 +1,3842 @@
   143.4 +/*
   143.5 + * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
   143.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   143.7 + *
   143.8 + * This code is free software; you can redistribute it and/or modify it
   143.9 + * under the terms of the GNU General Public License version 2 only, as
  143.10 + * published by the Free Software Foundation.  Oracle designates this
  143.11 + * particular file as subject to the "Classpath" exception as provided
  143.12 + * by Oracle in the LICENSE file that accompanied this code.
  143.13 + *
  143.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  143.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  143.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  143.17 + * version 2 for more details (a copy is included in the LICENSE file that
  143.18 + * accompanied this code).
  143.19 + *
  143.20 + * You should have received a copy of the GNU General Public License version
  143.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  143.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  143.23 + *
  143.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  143.25 + * or visit www.oracle.com if you need additional information or have any
  143.26 + * questions.
  143.27 + */
  143.28 +
  143.29 +/*
  143.30 + * Portions Copyright IBM Corporation, 2001. All Rights Reserved.
  143.31 + */
  143.32 +
  143.33 +package java.math;
  143.34 +
  143.35 +import java.util.Arrays;
  143.36 +import static java.math.BigInteger.LONG_MASK;
  143.37 +
  143.38 +/**
  143.39 + * Immutable, arbitrary-precision signed decimal numbers.  A
  143.40 + * {@code BigDecimal} consists of an arbitrary precision integer
  143.41 + * <i>unscaled value</i> and a 32-bit integer <i>scale</i>.  If zero
  143.42 + * or positive, the scale is the number of digits to the right of the
  143.43 + * decimal point.  If negative, the unscaled value of the number is
  143.44 + * multiplied by ten to the power of the negation of the scale.  The
  143.45 + * value of the number represented by the {@code BigDecimal} is
  143.46 + * therefore <tt>(unscaledValue &times; 10<sup>-scale</sup>)</tt>.
  143.47 + *
  143.48 + * <p>The {@code BigDecimal} class provides operations for
  143.49 + * arithmetic, scale manipulation, rounding, comparison, hashing, and
  143.50 + * format conversion.  The {@link #toString} method provides a
  143.51 + * canonical representation of a {@code BigDecimal}.
  143.52 + *
  143.53 + * <p>The {@code BigDecimal} class gives its user complete control
  143.54 + * over rounding behavior.  If no rounding mode is specified and the
  143.55 + * exact result cannot be represented, an exception is thrown;
  143.56 + * otherwise, calculations can be carried out to a chosen precision
  143.57 + * and rounding mode by supplying an appropriate {@link MathContext}
  143.58 + * object to the operation.  In either case, eight <em>rounding
  143.59 + * modes</em> are provided for the control of rounding.  Using the
  143.60 + * integer fields in this class (such as {@link #ROUND_HALF_UP}) to
  143.61 + * represent rounding mode is largely obsolete; the enumeration values
  143.62 + * of the {@code RoundingMode} {@code enum}, (such as {@link
  143.63 + * RoundingMode#HALF_UP}) should be used instead.
  143.64 + *
  143.65 + * <p>When a {@code MathContext} object is supplied with a precision
  143.66 + * setting of 0 (for example, {@link MathContext#UNLIMITED}),
  143.67 + * arithmetic operations are exact, as are the arithmetic methods
  143.68 + * which take no {@code MathContext} object.  (This is the only
  143.69 + * behavior that was supported in releases prior to 5.)  As a
  143.70 + * corollary of computing the exact result, the rounding mode setting
  143.71 + * of a {@code MathContext} object with a precision setting of 0 is
  143.72 + * not used and thus irrelevant.  In the case of divide, the exact
  143.73 + * quotient could have an infinitely long decimal expansion; for
  143.74 + * example, 1 divided by 3.  If the quotient has a nonterminating
  143.75 + * decimal expansion and the operation is specified to return an exact
  143.76 + * result, an {@code ArithmeticException} is thrown.  Otherwise, the
  143.77 + * exact result of the division is returned, as done for other
  143.78 + * operations.
  143.79 + *
  143.80 + * <p>When the precision setting is not 0, the rules of
  143.81 + * {@code BigDecimal} arithmetic are broadly compatible with selected
  143.82 + * modes of operation of the arithmetic defined in ANSI X3.274-1996
  143.83 + * and ANSI X3.274-1996/AM 1-2000 (section 7.4).  Unlike those
  143.84 + * standards, {@code BigDecimal} includes many rounding modes, which
  143.85 + * were mandatory for division in {@code BigDecimal} releases prior
  143.86 + * to 5.  Any conflicts between these ANSI standards and the
  143.87 + * {@code BigDecimal} specification are resolved in favor of
  143.88 + * {@code BigDecimal}.
  143.89 + *
  143.90 + * <p>Since the same numerical value can have different
  143.91 + * representations (with different scales), the rules of arithmetic
  143.92 + * and rounding must specify both the numerical result and the scale
  143.93 + * used in the result's representation.
  143.94 + *
  143.95 + *
  143.96 + * <p>In general the rounding modes and precision setting determine
  143.97 + * how operations return results with a limited number of digits when
  143.98 + * the exact result has more digits (perhaps infinitely many in the
  143.99 + * case of division) than the number of digits returned.
 143.100 + *
 143.101 + * First, the
 143.102 + * total number of digits to return is specified by the
 143.103 + * {@code MathContext}'s {@code precision} setting; this determines
 143.104 + * the result's <i>precision</i>.  The digit count starts from the
 143.105 + * leftmost nonzero digit of the exact result.  The rounding mode
 143.106 + * determines how any discarded trailing digits affect the returned
 143.107 + * result.
 143.108 + *
 143.109 + * <p>For all arithmetic operators , the operation is carried out as
 143.110 + * though an exact intermediate result were first calculated and then
 143.111 + * rounded to the number of digits specified by the precision setting
 143.112 + * (if necessary), using the selected rounding mode.  If the exact
 143.113 + * result is not returned, some digit positions of the exact result
 143.114 + * are discarded.  When rounding increases the magnitude of the
 143.115 + * returned result, it is possible for a new digit position to be
 143.116 + * created by a carry propagating to a leading {@literal "9"} digit.
 143.117 + * For example, rounding the value 999.9 to three digits rounding up
 143.118 + * would be numerically equal to one thousand, represented as
 143.119 + * 100&times;10<sup>1</sup>.  In such cases, the new {@literal "1"} is
 143.120 + * the leading digit position of the returned result.
 143.121 + *
 143.122 + * <p>Besides a logical exact result, each arithmetic operation has a
 143.123 + * preferred scale for representing a result.  The preferred
 143.124 + * scale for each operation is listed in the table below.
 143.125 + *
 143.126 + * <table border>
 143.127 + * <caption><b>Preferred Scales for Results of Arithmetic Operations
 143.128 + * </b></caption>
 143.129 + * <tr><th>Operation</th><th>Preferred Scale of Result</th></tr>
 143.130 + * <tr><td>Add</td><td>max(addend.scale(), augend.scale())</td>
 143.131 + * <tr><td>Subtract</td><td>max(minuend.scale(), subtrahend.scale())</td>
 143.132 + * <tr><td>Multiply</td><td>multiplier.scale() + multiplicand.scale()</td>
 143.133 + * <tr><td>Divide</td><td>dividend.scale() - divisor.scale()</td>
 143.134 + * </table>
 143.135 + *
 143.136 + * These scales are the ones used by the methods which return exact
 143.137 + * arithmetic results; except that an exact divide may have to use a
 143.138 + * larger scale since the exact result may have more digits.  For
 143.139 + * example, {@code 1/32} is {@code 0.03125}.
 143.140 + *
 143.141 + * <p>Before rounding, the scale of the logical exact intermediate
 143.142 + * result is the preferred scale for that operation.  If the exact
 143.143 + * numerical result cannot be represented in {@code precision}
 143.144 + * digits, rounding selects the set of digits to return and the scale
 143.145 + * of the result is reduced from the scale of the intermediate result
 143.146 + * to the least scale which can represent the {@code precision}
 143.147 + * digits actually returned.  If the exact result can be represented
 143.148 + * with at most {@code precision} digits, the representation
 143.149 + * of the result with the scale closest to the preferred scale is
 143.150 + * returned.  In particular, an exactly representable quotient may be
 143.151 + * represented in fewer than {@code precision} digits by removing
 143.152 + * trailing zeros and decreasing the scale.  For example, rounding to
 143.153 + * three digits using the {@linkplain RoundingMode#FLOOR floor}
 143.154 + * rounding mode, <br>
 143.155 + *
 143.156 + * {@code 19/100 = 0.19   // integer=19,  scale=2} <br>
 143.157 + *
 143.158 + * but<br>
 143.159 + *
 143.160 + * {@code 21/110 = 0.190  // integer=190, scale=3} <br>
 143.161 + *
 143.162 + * <p>Note that for add, subtract, and multiply, the reduction in
 143.163 + * scale will equal the number of digit positions of the exact result
 143.164 + * which are discarded. If the rounding causes a carry propagation to
 143.165 + * create a new high-order digit position, an additional digit of the
 143.166 + * result is discarded than when no new digit position is created.
 143.167 + *
 143.168 + * <p>Other methods may have slightly different rounding semantics.
 143.169 + * For example, the result of the {@code pow} method using the
 143.170 + * {@linkplain #pow(int, MathContext) specified algorithm} can
 143.171 + * occasionally differ from the rounded mathematical result by more
 143.172 + * than one unit in the last place, one <i>{@linkplain #ulp() ulp}</i>.
 143.173 + *
 143.174 + * <p>Two types of operations are provided for manipulating the scale
 143.175 + * of a {@code BigDecimal}: scaling/rounding operations and decimal
 143.176 + * point motion operations.  Scaling/rounding operations ({@link
 143.177 + * #setScale setScale} and {@link #round round}) return a
 143.178 + * {@code BigDecimal} whose value is approximately (or exactly) equal
 143.179 + * to that of the operand, but whose scale or precision is the
 143.180 + * specified value; that is, they increase or decrease the precision
 143.181 + * of the stored number with minimal effect on its value.  Decimal
 143.182 + * point motion operations ({@link #movePointLeft movePointLeft} and
 143.183 + * {@link #movePointRight movePointRight}) return a
 143.184 + * {@code BigDecimal} created from the operand by moving the decimal
 143.185 + * point a specified distance in the specified direction.
 143.186 + *
 143.187 + * <p>For the sake of brevity and clarity, pseudo-code is used
 143.188 + * throughout the descriptions of {@code BigDecimal} methods.  The
 143.189 + * pseudo-code expression {@code (i + j)} is shorthand for "a
 143.190 + * {@code BigDecimal} whose value is that of the {@code BigDecimal}
 143.191 + * {@code i} added to that of the {@code BigDecimal}
 143.192 + * {@code j}." The pseudo-code expression {@code (i == j)} is
 143.193 + * shorthand for "{@code true} if and only if the
 143.194 + * {@code BigDecimal} {@code i} represents the same value as the
 143.195 + * {@code BigDecimal} {@code j}." Other pseudo-code expressions
 143.196 + * are interpreted similarly.  Square brackets are used to represent
 143.197 + * the particular {@code BigInteger} and scale pair defining a
 143.198 + * {@code BigDecimal} value; for example [19, 2] is the
 143.199 + * {@code BigDecimal} numerically equal to 0.19 having a scale of 2.
 143.200 + *
 143.201 + * <p>Note: care should be exercised if {@code BigDecimal} objects
 143.202 + * are used as keys in a {@link java.util.SortedMap SortedMap} or
 143.203 + * elements in a {@link java.util.SortedSet SortedSet} since
 143.204 + * {@code BigDecimal}'s <i>natural ordering</i> is <i>inconsistent
 143.205 + * with equals</i>.  See {@link Comparable}, {@link
 143.206 + * java.util.SortedMap} or {@link java.util.SortedSet} for more
 143.207 + * information.
 143.208 + *
 143.209 + * <p>All methods and constructors for this class throw
 143.210 + * {@code NullPointerException} when passed a {@code null} object
 143.211 + * reference for any input parameter.
 143.212 + *
 143.213 + * @see     BigInteger
 143.214 + * @see     MathContext
 143.215 + * @see     RoundingMode
 143.216 + * @see     java.util.SortedMap
 143.217 + * @see     java.util.SortedSet
 143.218 + * @author  Josh Bloch
 143.219 + * @author  Mike Cowlishaw
 143.220 + * @author  Joseph D. Darcy
 143.221 + */
 143.222 +public class BigDecimal extends Number implements Comparable<BigDecimal> {
 143.223 +    /**
 143.224 +     * The unscaled value of this BigDecimal, as returned by {@link
 143.225 +     * #unscaledValue}.
 143.226 +     *
 143.227 +     * @serial
 143.228 +     * @see #unscaledValue
 143.229 +     */
 143.230 +    private volatile BigInteger intVal;
 143.231 +
 143.232 +    /**
 143.233 +     * The scale of this BigDecimal, as returned by {@link #scale}.
 143.234 +     *
 143.235 +     * @serial
 143.236 +     * @see #scale
 143.237 +     */
 143.238 +    private int scale;  // Note: this may have any value, so
 143.239 +                        // calculations must be done in longs
 143.240 +    /**
 143.241 +     * The number of decimal digits in this BigDecimal, or 0 if the
 143.242 +     * number of digits are not known (lookaside information).  If
 143.243 +     * nonzero, the value is guaranteed correct.  Use the precision()
 143.244 +     * method to obtain and set the value if it might be 0.  This
 143.245 +     * field is mutable until set nonzero.
 143.246 +     *
 143.247 +     * @since  1.5
 143.248 +     */
 143.249 +    private transient int precision;
 143.250 +
 143.251 +    /**
 143.252 +     * Used to store the canonical string representation, if computed.
 143.253 +     */
 143.254 +    private transient String stringCache;
 143.255 +
 143.256 +    /**
 143.257 +     * Sentinel value for {@link #intCompact} indicating the
 143.258 +     * significand information is only available from {@code intVal}.
 143.259 +     */
 143.260 +    static final long INFLATED = Long.MIN_VALUE;
 143.261 +
 143.262 +    /**
 143.263 +     * If the absolute value of the significand of this BigDecimal is
 143.264 +     * less than or equal to {@code Long.MAX_VALUE}, the value can be
 143.265 +     * compactly stored in this field and used in computations.
 143.266 +     */
 143.267 +    private transient long intCompact;
 143.268 +
 143.269 +    // All 18-digit base ten strings fit into a long; not all 19-digit
 143.270 +    // strings will
 143.271 +    private static final int MAX_COMPACT_DIGITS = 18;
 143.272 +
 143.273 +    private static final int MAX_BIGINT_BITS = 62;
 143.274 +
 143.275 +    /* Appease the serialization gods */
 143.276 +    private static final long serialVersionUID = 6108874887143696463L;
 143.277 +
 143.278 +    // Cache of common small BigDecimal values.
 143.279 +    private static final BigDecimal zeroThroughTen[] = {
 143.280 +        new BigDecimal(BigInteger.ZERO,         0,  0, 1),
 143.281 +        new BigDecimal(BigInteger.ONE,          1,  0, 1),
 143.282 +        new BigDecimal(BigInteger.valueOf(2),   2,  0, 1),
 143.283 +        new BigDecimal(BigInteger.valueOf(3),   3,  0, 1),
 143.284 +        new BigDecimal(BigInteger.valueOf(4),   4,  0, 1),
 143.285 +        new BigDecimal(BigInteger.valueOf(5),   5,  0, 1),
 143.286 +        new BigDecimal(BigInteger.valueOf(6),   6,  0, 1),
 143.287 +        new BigDecimal(BigInteger.valueOf(7),   7,  0, 1),
 143.288 +        new BigDecimal(BigInteger.valueOf(8),   8,  0, 1),
 143.289 +        new BigDecimal(BigInteger.valueOf(9),   9,  0, 1),
 143.290 +        new BigDecimal(BigInteger.TEN,          10, 0, 2),
 143.291 +    };
 143.292 +
 143.293 +    // Cache of zero scaled by 0 - 15
 143.294 +    private static final BigDecimal[] ZERO_SCALED_BY = {
 143.295 +        zeroThroughTen[0],
 143.296 +        new BigDecimal(BigInteger.ZERO, 0, 1, 1),
 143.297 +        new BigDecimal(BigInteger.ZERO, 0, 2, 1),
 143.298 +        new BigDecimal(BigInteger.ZERO, 0, 3, 1),
 143.299 +        new BigDecimal(BigInteger.ZERO, 0, 4, 1),
 143.300 +        new BigDecimal(BigInteger.ZERO, 0, 5, 1),
 143.301 +        new BigDecimal(BigInteger.ZERO, 0, 6, 1),
 143.302 +        new BigDecimal(BigInteger.ZERO, 0, 7, 1),
 143.303 +        new BigDecimal(BigInteger.ZERO, 0, 8, 1),
 143.304 +        new BigDecimal(BigInteger.ZERO, 0, 9, 1),
 143.305 +        new BigDecimal(BigInteger.ZERO, 0, 10, 1),
 143.306 +        new BigDecimal(BigInteger.ZERO, 0, 11, 1),
 143.307 +        new BigDecimal(BigInteger.ZERO, 0, 12, 1),
 143.308 +        new BigDecimal(BigInteger.ZERO, 0, 13, 1),
 143.309 +        new BigDecimal(BigInteger.ZERO, 0, 14, 1),
 143.310 +        new BigDecimal(BigInteger.ZERO, 0, 15, 1),
 143.311 +    };
 143.312 +
 143.313 +    // Half of Long.MIN_VALUE & Long.MAX_VALUE.
 143.314 +    private static final long HALF_LONG_MAX_VALUE = Long.MAX_VALUE / 2;
 143.315 +    private static final long HALF_LONG_MIN_VALUE = Long.MIN_VALUE / 2;
 143.316 +
 143.317 +    // Constants
 143.318 +    /**
 143.319 +     * The value 0, with a scale of 0.
 143.320 +     *
 143.321 +     * @since  1.5
 143.322 +     */
 143.323 +    public static final BigDecimal ZERO =
 143.324 +        zeroThroughTen[0];
 143.325 +
 143.326 +    /**
 143.327 +     * The value 1, with a scale of 0.
 143.328 +     *
 143.329 +     * @since  1.5
 143.330 +     */
 143.331 +    public static final BigDecimal ONE =
 143.332 +        zeroThroughTen[1];
 143.333 +
 143.334 +    /**
 143.335 +     * The value 10, with a scale of 0.
 143.336 +     *
 143.337 +     * @since  1.5
 143.338 +     */
 143.339 +    public static final BigDecimal TEN =
 143.340 +        zeroThroughTen[10];
 143.341 +
 143.342 +    // Constructors
 143.343 +
 143.344 +    /**
 143.345 +     * Trusted package private constructor.
 143.346 +     * Trusted simply means if val is INFLATED, intVal could not be null and
 143.347 +     * if intVal is null, val could not be INFLATED.
 143.348 +     */
 143.349 +    BigDecimal(BigInteger intVal, long val, int scale, int prec) {
 143.350 +        this.scale = scale;
 143.351 +        this.precision = prec;
 143.352 +        this.intCompact = val;
 143.353 +        this.intVal = intVal;
 143.354 +    }
 143.355 +
 143.356 +    /**
 143.357 +     * Translates a character array representation of a
 143.358 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 143.359 +     * same sequence of characters as the {@link #BigDecimal(String)}
 143.360 +     * constructor, while allowing a sub-array to be specified.
 143.361 +     *
 143.362 +     * <p>Note that if the sequence of characters is already available
 143.363 +     * within a character array, using this constructor is faster than
 143.364 +     * converting the {@code char} array to string and using the
 143.365 +     * {@code BigDecimal(String)} constructor .
 143.366 +     *
 143.367 +     * @param  in {@code char} array that is the source of characters.
 143.368 +     * @param  offset first character in the array to inspect.
 143.369 +     * @param  len number of characters to consider.
 143.370 +     * @throws NumberFormatException if {@code in} is not a valid
 143.371 +     *         representation of a {@code BigDecimal} or the defined subarray
 143.372 +     *         is not wholly within {@code in}.
 143.373 +     * @since  1.5
 143.374 +     */
 143.375 +    public BigDecimal(char[] in, int offset, int len) {
 143.376 +        // protect against huge length.
 143.377 +        if (offset+len > in.length || offset < 0)
 143.378 +            throw new NumberFormatException();
 143.379 +        // This is the primary string to BigDecimal constructor; all
 143.380 +        // incoming strings end up here; it uses explicit (inline)
 143.381 +        // parsing for speed and generates at most one intermediate
 143.382 +        // (temporary) object (a char[] array) for non-compact case.
 143.383 +
 143.384 +        // Use locals for all fields values until completion
 143.385 +        int prec = 0;                 // record precision value
 143.386 +        int scl = 0;                  // record scale value
 143.387 +        long rs = 0;                  // the compact value in long
 143.388 +        BigInteger rb = null;         // the inflated value in BigInteger
 143.389 +
 143.390 +        // use array bounds checking to handle too-long, len == 0,
 143.391 +        // bad offset, etc.
 143.392 +        try {
 143.393 +            // handle the sign
 143.394 +            boolean isneg = false;          // assume positive
 143.395 +            if (in[offset] == '-') {
 143.396 +                isneg = true;               // leading minus means negative
 143.397 +                offset++;
 143.398 +                len--;
 143.399 +            } else if (in[offset] == '+') { // leading + allowed
 143.400 +                offset++;
 143.401 +                len--;
 143.402 +            }
 143.403 +
 143.404 +            // should now be at numeric part of the significand
 143.405 +            boolean dot = false;             // true when there is a '.'
 143.406 +            int cfirst = offset;             // record start of integer
 143.407 +            long exp = 0;                    // exponent
 143.408 +            char c;                          // current character
 143.409 +
 143.410 +            boolean isCompact = (len <= MAX_COMPACT_DIGITS);
 143.411 +            // integer significand array & idx is the index to it. The array
 143.412 +            // is ONLY used when we can't use a compact representation.
 143.413 +            char coeff[] = isCompact ? null : new char[len];
 143.414 +            int idx = 0;
 143.415 +
 143.416 +            for (; len > 0; offset++, len--) {
 143.417 +                c = in[offset];
 143.418 +                // have digit
 143.419 +                if ((c >= '0' && c <= '9') || Character.isDigit(c)) {
 143.420 +                    // First compact case, we need not to preserve the character
 143.421 +                    // and we can just compute the value in place.
 143.422 +                    if (isCompact) {
 143.423 +                        int digit = Character.digit(c, 10);
 143.424 +                        if (digit == 0) {
 143.425 +                            if (prec == 0)
 143.426 +                                prec = 1;
 143.427 +                            else if (rs != 0) {
 143.428 +                                rs *= 10;
 143.429 +                                ++prec;
 143.430 +                            } // else digit is a redundant leading zero
 143.431 +                        } else {
 143.432 +                            if (prec != 1 || rs != 0)
 143.433 +                                ++prec; // prec unchanged if preceded by 0s
 143.434 +                            rs = rs * 10 + digit;
 143.435 +                        }
 143.436 +                    } else { // the unscaled value is likely a BigInteger object.
 143.437 +                        if (c == '0' || Character.digit(c, 10) == 0) {
 143.438 +                            if (prec == 0) {
 143.439 +                                coeff[idx] = c;
 143.440 +                                prec = 1;
 143.441 +                            } else if (idx != 0) {
 143.442 +                                coeff[idx++] = c;
 143.443 +                                ++prec;
 143.444 +                            } // else c must be a redundant leading zero
 143.445 +                        } else {
 143.446 +                            if (prec != 1 || idx != 0)
 143.447 +                                ++prec; // prec unchanged if preceded by 0s
 143.448 +                            coeff[idx++] = c;
 143.449 +                        }
 143.450 +                    }
 143.451 +                    if (dot)
 143.452 +                        ++scl;
 143.453 +                    continue;
 143.454 +                }
 143.455 +                // have dot
 143.456 +                if (c == '.') {
 143.457 +                    // have dot
 143.458 +                    if (dot)         // two dots
 143.459 +                        throw new NumberFormatException();
 143.460 +                    dot = true;
 143.461 +                    continue;
 143.462 +                }
 143.463 +                // exponent expected
 143.464 +                if ((c != 'e') && (c != 'E'))
 143.465 +                    throw new NumberFormatException();
 143.466 +                offset++;
 143.467 +                c = in[offset];
 143.468 +                len--;
 143.469 +                boolean negexp = (c == '-');
 143.470 +                // optional sign
 143.471 +                if (negexp || c == '+') {
 143.472 +                    offset++;
 143.473 +                    c = in[offset];
 143.474 +                    len--;
 143.475 +                }
 143.476 +                if (len <= 0)    // no exponent digits
 143.477 +                    throw new NumberFormatException();
 143.478 +                // skip leading zeros in the exponent
 143.479 +                while (len > 10 && Character.digit(c, 10) == 0) {
 143.480 +                    offset++;
 143.481 +                    c = in[offset];
 143.482 +                    len--;
 143.483 +                }
 143.484 +                if (len > 10)  // too many nonzero exponent digits
 143.485 +                    throw new NumberFormatException();
 143.486 +                // c now holds first digit of exponent
 143.487 +                for (;; len--) {
 143.488 +                    int v;
 143.489 +                    if (c >= '0' && c <= '9') {
 143.490 +                        v = c - '0';
 143.491 +                    } else {
 143.492 +                        v = Character.digit(c, 10);
 143.493 +                        if (v < 0)            // not a digit
 143.494 +                            throw new NumberFormatException();
 143.495 +                    }
 143.496 +                    exp = exp * 10 + v;
 143.497 +                    if (len == 1)
 143.498 +                        break;               // that was final character
 143.499 +                    offset++;
 143.500 +                    c = in[offset];
 143.501 +                }
 143.502 +                if (negexp)                  // apply sign
 143.503 +                    exp = -exp;
 143.504 +                // Next test is required for backwards compatibility
 143.505 +                if ((int)exp != exp)         // overflow
 143.506 +                    throw new NumberFormatException();
 143.507 +                break;                       // [saves a test]
 143.508 +            }
 143.509 +            // here when no characters left
 143.510 +            if (prec == 0)              // no digits found
 143.511 +                throw new NumberFormatException();
 143.512 +
 143.513 +            // Adjust scale if exp is not zero.
 143.514 +            if (exp != 0) {                  // had significant exponent
 143.515 +                // Can't call checkScale which relies on proper fields value
 143.516 +                long adjustedScale = scl - exp;
 143.517 +                if (adjustedScale > Integer.MAX_VALUE ||
 143.518 +                    adjustedScale < Integer.MIN_VALUE)
 143.519 +                    throw new NumberFormatException("Scale out of range.");
 143.520 +                scl = (int)adjustedScale;
 143.521 +            }
 143.522 +
 143.523 +            // Remove leading zeros from precision (digits count)
 143.524 +            if (isCompact) {
 143.525 +                rs = isneg ? -rs : rs;
 143.526 +            } else {
 143.527 +                char quick[];
 143.528 +                if (!isneg) {
 143.529 +                    quick = (coeff.length != prec) ?
 143.530 +                        Arrays.copyOf(coeff, prec) : coeff;
 143.531 +                } else {
 143.532 +                    quick = new char[prec + 1];
 143.533 +                    quick[0] = '-';
 143.534 +                    System.arraycopy(coeff, 0, quick, 1, prec);
 143.535 +                }
 143.536 +                rb = new BigInteger(quick);
 143.537 +                rs = compactValFor(rb);
 143.538 +            }
 143.539 +        } catch (ArrayIndexOutOfBoundsException e) {
 143.540 +            throw new NumberFormatException();
 143.541 +        } catch (NegativeArraySizeException e) {
 143.542 +            throw new NumberFormatException();
 143.543 +        }
 143.544 +        this.scale = scl;
 143.545 +        this.precision = prec;
 143.546 +        this.intCompact = rs;
 143.547 +        this.intVal = (rs != INFLATED) ? null : rb;
 143.548 +    }
 143.549 +
 143.550 +    /**
 143.551 +     * Translates a character array representation of a
 143.552 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 143.553 +     * same sequence of characters as the {@link #BigDecimal(String)}
 143.554 +     * constructor, while allowing a sub-array to be specified and
 143.555 +     * with rounding according to the context settings.
 143.556 +     *
 143.557 +     * <p>Note that if the sequence of characters is already available
 143.558 +     * within a character array, using this constructor is faster than
 143.559 +     * converting the {@code char} array to string and using the
 143.560 +     * {@code BigDecimal(String)} constructor .
 143.561 +     *
 143.562 +     * @param  in {@code char} array that is the source of characters.
 143.563 +     * @param  offset first character in the array to inspect.
 143.564 +     * @param  len number of characters to consider..
 143.565 +     * @param  mc the context to use.
 143.566 +     * @throws ArithmeticException if the result is inexact but the
 143.567 +     *         rounding mode is {@code UNNECESSARY}.
 143.568 +     * @throws NumberFormatException if {@code in} is not a valid
 143.569 +     *         representation of a {@code BigDecimal} or the defined subarray
 143.570 +     *         is not wholly within {@code in}.
 143.571 +     * @since  1.5
 143.572 +     */
 143.573 +    public BigDecimal(char[] in, int offset, int len, MathContext mc) {
 143.574 +        this(in, offset, len);
 143.575 +        if (mc.precision > 0)
 143.576 +            roundThis(mc);
 143.577 +    }
 143.578 +
 143.579 +    /**
 143.580 +     * Translates a character array representation of a
 143.581 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 143.582 +     * same sequence of characters as the {@link #BigDecimal(String)}
 143.583 +     * constructor.
 143.584 +     *
 143.585 +     * <p>Note that if the sequence of characters is already available
 143.586 +     * as a character array, using this constructor is faster than
 143.587 +     * converting the {@code char} array to string and using the
 143.588 +     * {@code BigDecimal(String)} constructor .
 143.589 +     *
 143.590 +     * @param in {@code char} array that is the source of characters.
 143.591 +     * @throws NumberFormatException if {@code in} is not a valid
 143.592 +     *         representation of a {@code BigDecimal}.
 143.593 +     * @since  1.5
 143.594 +     */
 143.595 +    public BigDecimal(char[] in) {
 143.596 +        this(in, 0, in.length);
 143.597 +    }
 143.598 +
 143.599 +    /**
 143.600 +     * Translates a character array representation of a
 143.601 +     * {@code BigDecimal} into a {@code BigDecimal}, accepting the
 143.602 +     * same sequence of characters as the {@link #BigDecimal(String)}
 143.603 +     * constructor and with rounding according to the context
 143.604 +     * settings.
 143.605 +     *
 143.606 +     * <p>Note that if the sequence of characters is already available
 143.607 +     * as a character array, using this constructor is faster than
 143.608 +     * converting the {@code char} array to string and using the
 143.609 +     * {@code BigDecimal(String)} constructor .
 143.610 +     *
 143.611 +     * @param  in {@code char} array that is the source of characters.
 143.612 +     * @param  mc the context to use.
 143.613 +     * @throws ArithmeticException if the result is inexact but the
 143.614 +     *         rounding mode is {@code UNNECESSARY}.
 143.615 +     * @throws NumberFormatException if {@code in} is not a valid
 143.616 +     *         representation of a {@code BigDecimal}.
 143.617 +     * @since  1.5
 143.618 +     */
 143.619 +    public BigDecimal(char[] in, MathContext mc) {
 143.620 +        this(in, 0, in.length, mc);
 143.621 +    }
 143.622 +
 143.623 +    /**
 143.624 +     * Translates the string representation of a {@code BigDecimal}
 143.625 +     * into a {@code BigDecimal}.  The string representation consists
 143.626 +     * of an optional sign, {@code '+'} (<tt> '&#92;u002B'</tt>) or
 143.627 +     * {@code '-'} (<tt>'&#92;u002D'</tt>), followed by a sequence of
 143.628 +     * zero or more decimal digits ("the integer"), optionally
 143.629 +     * followed by a fraction, optionally followed by an exponent.
 143.630 +     *
 143.631 +     * <p>The fraction consists of a decimal point followed by zero
 143.632 +     * or more decimal digits.  The string must contain at least one
 143.633 +     * digit in either the integer or the fraction.  The number formed
 143.634 +     * by the sign, the integer and the fraction is referred to as the
 143.635 +     * <i>significand</i>.
 143.636 +     *
 143.637 +     * <p>The exponent consists of the character {@code 'e'}
 143.638 +     * (<tt>'&#92;u0065'</tt>) or {@code 'E'} (<tt>'&#92;u0045'</tt>)
 143.639 +     * followed by one or more decimal digits.  The value of the
 143.640 +     * exponent must lie between -{@link Integer#MAX_VALUE} ({@link
 143.641 +     * Integer#MIN_VALUE}+1) and {@link Integer#MAX_VALUE}, inclusive.
 143.642 +     *
 143.643 +     * <p>More formally, the strings this constructor accepts are
 143.644 +     * described by the following grammar:
 143.645 +     * <blockquote>
 143.646 +     * <dl>
 143.647 +     * <dt><i>BigDecimalString:</i>
 143.648 +     * <dd><i>Sign<sub>opt</sub> Significand Exponent<sub>opt</sub></i>
 143.649 +     * <p>
 143.650 +     * <dt><i>Sign:</i>
 143.651 +     * <dd>{@code +}
 143.652 +     * <dd>{@code -}
 143.653 +     * <p>
 143.654 +     * <dt><i>Significand:</i>
 143.655 +     * <dd><i>IntegerPart</i> {@code .} <i>FractionPart<sub>opt</sub></i>
 143.656 +     * <dd>{@code .} <i>FractionPart</i>
 143.657 +     * <dd><i>IntegerPart</i>
 143.658 +     * <p>
 143.659 +     * <dt><i>IntegerPart:</i>
 143.660 +     * <dd><i>Digits</i>
 143.661 +     * <p>
 143.662 +     * <dt><i>FractionPart:</i>
 143.663 +     * <dd><i>Digits</i>
 143.664 +     * <p>
 143.665 +     * <dt><i>Exponent:</i>
 143.666 +     * <dd><i>ExponentIndicator SignedInteger</i>
 143.667 +     * <p>
 143.668 +     * <dt><i>ExponentIndicator:</i>
 143.669 +     * <dd>{@code e}
 143.670 +     * <dd>{@code E}
 143.671 +     * <p>
 143.672 +     * <dt><i>SignedInteger:</i>
 143.673 +     * <dd><i>Sign<sub>opt</sub> Digits</i>
 143.674 +     * <p>
 143.675 +     * <dt><i>Digits:</i>
 143.676 +     * <dd><i>Digit</i>
 143.677 +     * <dd><i>Digits Digit</i>
 143.678 +     * <p>
 143.679 +     * <dt><i>Digit:</i>
 143.680 +     * <dd>any character for which {@link Character#isDigit}
 143.681 +     * returns {@code true}, including 0, 1, 2 ...
 143.682 +     * </dl>
 143.683 +     * </blockquote>
 143.684 +     *
 143.685 +     * <p>The scale of the returned {@code BigDecimal} will be the
 143.686 +     * number of digits in the fraction, or zero if the string
 143.687 +     * contains no decimal point, subject to adjustment for any
 143.688 +     * exponent; if the string contains an exponent, the exponent is
 143.689 +     * subtracted from the scale.  The value of the resulting scale
 143.690 +     * must lie between {@code Integer.MIN_VALUE} and
 143.691 +     * {@code Integer.MAX_VALUE}, inclusive.
 143.692 +     *
 143.693 +     * <p>The character-to-digit mapping is provided by {@link
 143.694 +     * java.lang.Character#digit} set to convert to radix 10.  The
 143.695 +     * String may not contain any extraneous characters (whitespace,
 143.696 +     * for example).
 143.697 +     *
 143.698 +     * <p><b>Examples:</b><br>
 143.699 +     * The value of the returned {@code BigDecimal} is equal to
 143.700 +     * <i>significand</i> &times; 10<sup>&nbsp;<i>exponent</i></sup>.
 143.701 +     * For each string on the left, the resulting representation
 143.702 +     * [{@code BigInteger}, {@code scale}] is shown on the right.
 143.703 +     * <pre>
 143.704 +     * "0"            [0,0]
 143.705 +     * "0.00"         [0,2]
 143.706 +     * "123"          [123,0]
 143.707 +     * "-123"         [-123,0]
 143.708 +     * "1.23E3"       [123,-1]
 143.709 +     * "1.23E+3"      [123,-1]
 143.710 +     * "12.3E+7"      [123,-6]
 143.711 +     * "12.0"         [120,1]
 143.712 +     * "12.3"         [123,1]
 143.713 +     * "0.00123"      [123,5]
 143.714 +     * "-1.23E-12"    [-123,14]
 143.715 +     * "1234.5E-4"    [12345,5]
 143.716 +     * "0E+7"         [0,-7]
 143.717 +     * "-0"           [0,0]
 143.718 +     * </pre>
 143.719 +     *
 143.720 +     * <p>Note: For values other than {@code float} and
 143.721 +     * {@code double} NaN and &plusmn;Infinity, this constructor is
 143.722 +     * compatible with the values returned by {@link Float#toString}
 143.723 +     * and {@link Double#toString}.  This is generally the preferred
 143.724 +     * way to convert a {@code float} or {@code double} into a
 143.725 +     * BigDecimal, as it doesn't suffer from the unpredictability of
 143.726 +     * the {@link #BigDecimal(double)} constructor.
 143.727 +     *
 143.728 +     * @param val String representation of {@code BigDecimal}.
 143.729 +     *
 143.730 +     * @throws NumberFormatException if {@code val} is not a valid
 143.731 +     *         representation of a {@code BigDecimal}.
 143.732 +     */
 143.733 +    public BigDecimal(String val) {
 143.734 +        this(val.toCharArray(), 0, val.length());
 143.735 +    }
 143.736 +
 143.737 +    /**
 143.738 +     * Translates the string representation of a {@code BigDecimal}
 143.739 +     * into a {@code BigDecimal}, accepting the same strings as the
 143.740 +     * {@link #BigDecimal(String)} constructor, with rounding
 143.741 +     * according to the context settings.
 143.742 +     *
 143.743 +     * @param  val string representation of a {@code BigDecimal}.
 143.744 +     * @param  mc the context to use.
 143.745 +     * @throws ArithmeticException if the result is inexact but the
 143.746 +     *         rounding mode is {@code UNNECESSARY}.
 143.747 +     * @throws NumberFormatException if {@code val} is not a valid
 143.748 +     *         representation of a BigDecimal.
 143.749 +     * @since  1.5
 143.750 +     */
 143.751 +    public BigDecimal(String val, MathContext mc) {
 143.752 +        this(val.toCharArray(), 0, val.length());
 143.753 +        if (mc.precision > 0)
 143.754 +            roundThis(mc);
 143.755 +    }
 143.756 +
 143.757 +    /**
 143.758 +     * Translates a {@code double} into a {@code BigDecimal} which
 143.759 +     * is the exact decimal representation of the {@code double}'s
 143.760 +     * binary floating-point value.  The scale of the returned
 143.761 +     * {@code BigDecimal} is the smallest value such that
 143.762 +     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
 143.763 +     * <p>
 143.764 +     * <b>Notes:</b>
 143.765 +     * <ol>
 143.766 +     * <li>
 143.767 +     * The results of this constructor can be somewhat unpredictable.
 143.768 +     * One might assume that writing {@code new BigDecimal(0.1)} in
 143.769 +     * Java creates a {@code BigDecimal} which is exactly equal to
 143.770 +     * 0.1 (an unscaled value of 1, with a scale of 1), but it is
 143.771 +     * actually equal to
 143.772 +     * 0.1000000000000000055511151231257827021181583404541015625.
 143.773 +     * This is because 0.1 cannot be represented exactly as a
 143.774 +     * {@code double} (or, for that matter, as a binary fraction of
 143.775 +     * any finite length).  Thus, the value that is being passed
 143.776 +     * <i>in</i> to the constructor is not exactly equal to 0.1,
 143.777 +     * appearances notwithstanding.
 143.778 +     *
 143.779 +     * <li>
 143.780 +     * The {@code String} constructor, on the other hand, is
 143.781 +     * perfectly predictable: writing {@code new BigDecimal("0.1")}
 143.782 +     * creates a {@code BigDecimal} which is <i>exactly</i> equal to
 143.783 +     * 0.1, as one would expect.  Therefore, it is generally
 143.784 +     * recommended that the {@linkplain #BigDecimal(String)
 143.785 +     * <tt>String</tt> constructor} be used in preference to this one.
 143.786 +     *
 143.787 +     * <li>
 143.788 +     * When a {@code double} must be used as a source for a
 143.789 +     * {@code BigDecimal}, note that this constructor provides an
 143.790 +     * exact conversion; it does not give the same result as
 143.791 +     * converting the {@code double} to a {@code String} using the
 143.792 +     * {@link Double#toString(double)} method and then using the
 143.793 +     * {@link #BigDecimal(String)} constructor.  To get that result,
 143.794 +     * use the {@code static} {@link #valueOf(double)} method.
 143.795 +     * </ol>
 143.796 +     *
 143.797 +     * @param val {@code double} value to be converted to
 143.798 +     *        {@code BigDecimal}.
 143.799 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
 143.800 +     */
 143.801 +    public BigDecimal(double val) {
 143.802 +        if (Double.isInfinite(val) || Double.isNaN(val))
 143.803 +            throw new NumberFormatException("Infinite or NaN");
 143.804 +
 143.805 +        // Translate the double into sign, exponent and significand, according
 143.806 +        // to the formulae in JLS, Section 20.10.22.
 143.807 +        long valBits = Double.doubleToLongBits(val);
 143.808 +        int sign = ((valBits >> 63)==0 ? 1 : -1);
 143.809 +        int exponent = (int) ((valBits >> 52) & 0x7ffL);
 143.810 +        long significand = (exponent==0 ? (valBits & ((1L<<52) - 1)) << 1
 143.811 +                            : (valBits & ((1L<<52) - 1)) | (1L<<52));
 143.812 +        exponent -= 1075;
 143.813 +        // At this point, val == sign * significand * 2**exponent.
 143.814 +
 143.815 +        /*
 143.816 +         * Special case zero to supress nonterminating normalization
 143.817 +         * and bogus scale calculation.
 143.818 +         */
 143.819 +        if (significand == 0) {
 143.820 +            intVal = BigInteger.ZERO;
 143.821 +            intCompact = 0;
 143.822 +            precision = 1;
 143.823 +            return;
 143.824 +        }
 143.825 +
 143.826 +        // Normalize
 143.827 +        while((significand & 1) == 0) {    //  i.e., significand is even
 143.828 +            significand >>= 1;
 143.829 +            exponent++;
 143.830 +        }
 143.831 +
 143.832 +        // Calculate intVal and scale
 143.833 +        long s = sign * significand;
 143.834 +        BigInteger b;
 143.835 +        if (exponent < 0) {
 143.836 +            b = BigInteger.valueOf(5).pow(-exponent).multiply(s);
 143.837 +            scale = -exponent;
 143.838 +        } else if (exponent > 0) {
 143.839 +            b = BigInteger.valueOf(2).pow(exponent).multiply(s);
 143.840 +        } else {
 143.841 +            b = BigInteger.valueOf(s);
 143.842 +        }
 143.843 +        intCompact = compactValFor(b);
 143.844 +        intVal = (intCompact != INFLATED) ? null : b;
 143.845 +    }
 143.846 +
 143.847 +    /**
 143.848 +     * Translates a {@code double} into a {@code BigDecimal}, with
 143.849 +     * rounding according to the context settings.  The scale of the
 143.850 +     * {@code BigDecimal} is the smallest value such that
 143.851 +     * <tt>(10<sup>scale</sup> &times; val)</tt> is an integer.
 143.852 +     *
 143.853 +     * <p>The results of this constructor can be somewhat unpredictable
 143.854 +     * and its use is generally not recommended; see the notes under
 143.855 +     * the {@link #BigDecimal(double)} constructor.
 143.856 +     *
 143.857 +     * @param  val {@code double} value to be converted to
 143.858 +     *         {@code BigDecimal}.
 143.859 +     * @param  mc the context to use.
 143.860 +     * @throws ArithmeticException if the result is inexact but the
 143.861 +     *         RoundingMode is UNNECESSARY.
 143.862 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
 143.863 +     * @since  1.5
 143.864 +     */
 143.865 +    public BigDecimal(double val, MathContext mc) {
 143.866 +        this(val);
 143.867 +        if (mc.precision > 0)
 143.868 +            roundThis(mc);
 143.869 +    }
 143.870 +
 143.871 +    /**
 143.872 +     * Translates a {@code BigInteger} into a {@code BigDecimal}.
 143.873 +     * The scale of the {@code BigDecimal} is zero.
 143.874 +     *
 143.875 +     * @param val {@code BigInteger} value to be converted to
 143.876 +     *            {@code BigDecimal}.
 143.877 +     */
 143.878 +    public BigDecimal(BigInteger val) {
 143.879 +        intCompact = compactValFor(val);
 143.880 +        intVal = (intCompact != INFLATED) ? null : val;
 143.881 +    }
 143.882 +
 143.883 +    /**
 143.884 +     * Translates a {@code BigInteger} into a {@code BigDecimal}
 143.885 +     * rounding according to the context settings.  The scale of the
 143.886 +     * {@code BigDecimal} is zero.
 143.887 +     *
 143.888 +     * @param val {@code BigInteger} value to be converted to
 143.889 +     *            {@code BigDecimal}.
 143.890 +     * @param  mc the context to use.
 143.891 +     * @throws ArithmeticException if the result is inexact but the
 143.892 +     *         rounding mode is {@code UNNECESSARY}.
 143.893 +     * @since  1.5
 143.894 +     */
 143.895 +    public BigDecimal(BigInteger val, MathContext mc) {
 143.896 +        this(val);
 143.897 +        if (mc.precision > 0)
 143.898 +            roundThis(mc);
 143.899 +    }
 143.900 +
 143.901 +    /**
 143.902 +     * Translates a {@code BigInteger} unscaled value and an
 143.903 +     * {@code int} scale into a {@code BigDecimal}.  The value of
 143.904 +     * the {@code BigDecimal} is
 143.905 +     * <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
 143.906 +     *
 143.907 +     * @param unscaledVal unscaled value of the {@code BigDecimal}.
 143.908 +     * @param scale scale of the {@code BigDecimal}.
 143.909 +     */
 143.910 +    public BigDecimal(BigInteger unscaledVal, int scale) {
 143.911 +        // Negative scales are now allowed
 143.912 +        this(unscaledVal);
 143.913 +        this.scale = scale;
 143.914 +    }
 143.915 +
 143.916 +    /**
 143.917 +     * Translates a {@code BigInteger} unscaled value and an
 143.918 +     * {@code int} scale into a {@code BigDecimal}, with rounding
 143.919 +     * according to the context settings.  The value of the
 143.920 +     * {@code BigDecimal} is <tt>(unscaledVal &times;
 143.921 +     * 10<sup>-scale</sup>)</tt>, rounded according to the
 143.922 +     * {@code precision} and rounding mode settings.
 143.923 +     *
 143.924 +     * @param  unscaledVal unscaled value of the {@code BigDecimal}.
 143.925 +     * @param  scale scale of the {@code BigDecimal}.
 143.926 +     * @param  mc the context to use.
 143.927 +     * @throws ArithmeticException if the result is inexact but the
 143.928 +     *         rounding mode is {@code UNNECESSARY}.
 143.929 +     * @since  1.5
 143.930 +     */
 143.931 +    public BigDecimal(BigInteger unscaledVal, int scale, MathContext mc) {
 143.932 +        this(unscaledVal);
 143.933 +        this.scale = scale;
 143.934 +        if (mc.precision > 0)
 143.935 +            roundThis(mc);
 143.936 +    }
 143.937 +
 143.938 +    /**
 143.939 +     * Translates an {@code int} into a {@code BigDecimal}.  The
 143.940 +     * scale of the {@code BigDecimal} is zero.
 143.941 +     *
 143.942 +     * @param val {@code int} value to be converted to
 143.943 +     *            {@code BigDecimal}.
 143.944 +     * @since  1.5
 143.945 +     */
 143.946 +    public BigDecimal(int val) {
 143.947 +        intCompact = val;
 143.948 +    }
 143.949 +
 143.950 +    /**
 143.951 +     * Translates an {@code int} into a {@code BigDecimal}, with
 143.952 +     * rounding according to the context settings.  The scale of the
 143.953 +     * {@code BigDecimal}, before any rounding, is zero.
 143.954 +     *
 143.955 +     * @param  val {@code int} value to be converted to {@code BigDecimal}.
 143.956 +     * @param  mc the context to use.
 143.957 +     * @throws ArithmeticException if the result is inexact but the
 143.958 +     *         rounding mode is {@code UNNECESSARY}.
 143.959 +     * @since  1.5
 143.960 +     */
 143.961 +    public BigDecimal(int val, MathContext mc) {
 143.962 +        intCompact = val;
 143.963 +        if (mc.precision > 0)
 143.964 +            roundThis(mc);
 143.965 +    }
 143.966 +
 143.967 +    /**
 143.968 +     * Translates a {@code long} into a {@code BigDecimal}.  The
 143.969 +     * scale of the {@code BigDecimal} is zero.
 143.970 +     *
 143.971 +     * @param val {@code long} value to be converted to {@code BigDecimal}.
 143.972 +     * @since  1.5
 143.973 +     */
 143.974 +    public BigDecimal(long val) {
 143.975 +        this.intCompact = val;
 143.976 +        this.intVal = (val == INFLATED) ? BigInteger.valueOf(val) : null;
 143.977 +    }
 143.978 +
 143.979 +    /**
 143.980 +     * Translates a {@code long} into a {@code BigDecimal}, with
 143.981 +     * rounding according to the context settings.  The scale of the
 143.982 +     * {@code BigDecimal}, before any rounding, is zero.
 143.983 +     *
 143.984 +     * @param  val {@code long} value to be converted to {@code BigDecimal}.
 143.985 +     * @param  mc the context to use.
 143.986 +     * @throws ArithmeticException if the result is inexact but the
 143.987 +     *         rounding mode is {@code UNNECESSARY}.
 143.988 +     * @since  1.5
 143.989 +     */
 143.990 +    public BigDecimal(long val, MathContext mc) {
 143.991 +        this(val);
 143.992 +        if (mc.precision > 0)
 143.993 +            roundThis(mc);
 143.994 +    }
 143.995 +
 143.996 +    // Static Factory Methods
 143.997 +
 143.998 +    /**
 143.999 +     * Translates a {@code long} unscaled value and an
143.1000 +     * {@code int} scale into a {@code BigDecimal}.  This
143.1001 +     * {@literal "static factory method"} is provided in preference to
143.1002 +     * a ({@code long}, {@code int}) constructor because it
143.1003 +     * allows for reuse of frequently used {@code BigDecimal} values..
143.1004 +     *
143.1005 +     * @param unscaledVal unscaled value of the {@code BigDecimal}.
143.1006 +     * @param scale scale of the {@code BigDecimal}.
143.1007 +     * @return a {@code BigDecimal} whose value is
143.1008 +     *         <tt>(unscaledVal &times; 10<sup>-scale</sup>)</tt>.
143.1009 +     */
143.1010 +    public static BigDecimal valueOf(long unscaledVal, int scale) {
143.1011 +        if (scale == 0)
143.1012 +            return valueOf(unscaledVal);
143.1013 +        else if (unscaledVal == 0) {
143.1014 +            if (scale > 0 && scale < ZERO_SCALED_BY.length)
143.1015 +                return ZERO_SCALED_BY[scale];
143.1016 +            else
143.1017 +                return new BigDecimal(BigInteger.ZERO, 0, scale, 1);
143.1018 +        }
143.1019 +        return new BigDecimal(unscaledVal == INFLATED ?
143.1020 +                              BigInteger.valueOf(unscaledVal) : null,
143.1021 +                              unscaledVal, scale, 0);
143.1022 +    }
143.1023 +
143.1024 +    /**
143.1025 +     * Translates a {@code long} value into a {@code BigDecimal}
143.1026 +     * with a scale of zero.  This {@literal "static factory method"}
143.1027 +     * is provided in preference to a ({@code long}) constructor
143.1028 +     * because it allows for reuse of frequently used
143.1029 +     * {@code BigDecimal} values.
143.1030 +     *
143.1031 +     * @param val value of the {@code BigDecimal}.
143.1032 +     * @return a {@code BigDecimal} whose value is {@code val}.
143.1033 +     */
143.1034 +    public static BigDecimal valueOf(long val) {
143.1035 +        if (val >= 0 && val < zeroThroughTen.length)
143.1036 +            return zeroThroughTen[(int)val];
143.1037 +        else if (val != INFLATED)
143.1038 +            return new BigDecimal(null, val, 0, 0);
143.1039 +        return new BigDecimal(BigInteger.valueOf(val), val, 0, 0);
143.1040 +    }
143.1041 +
143.1042 +    /**
143.1043 +     * Translates a {@code double} into a {@code BigDecimal}, using
143.1044 +     * the {@code double}'s canonical string representation provided
143.1045 +     * by the {@link Double#toString(double)} method.
143.1046 +     *
143.1047 +     * <p><b>Note:</b> This is generally the preferred way to convert
143.1048 +     * a {@code double} (or {@code float}) into a
143.1049 +     * {@code BigDecimal}, as the value returned is equal to that
143.1050 +     * resulting from constructing a {@code BigDecimal} from the
143.1051 +     * result of using {@link Double#toString(double)}.
143.1052 +     *
143.1053 +     * @param  val {@code double} to convert to a {@code BigDecimal}.
143.1054 +     * @return a {@code BigDecimal} whose value is equal to or approximately
143.1055 +     *         equal to the value of {@code val}.
143.1056 +     * @throws NumberFormatException if {@code val} is infinite or NaN.
143.1057 +     * @since  1.5
143.1058 +     */
143.1059 +    public static BigDecimal valueOf(double val) {
143.1060 +        // Reminder: a zero double returns '0.0', so we cannot fastpath
143.1061 +        // to use the constant ZERO.  This might be important enough to
143.1062 +        // justify a factory approach, a cache, or a few private
143.1063 +        // constants, later.
143.1064 +        return new BigDecimal(Double.toString(val));
143.1065 +    }
143.1066 +
143.1067 +    // Arithmetic Operations
143.1068 +    /**
143.1069 +     * Returns a {@code BigDecimal} whose value is {@code (this +
143.1070 +     * augend)}, and whose scale is {@code max(this.scale(),
143.1071 +     * augend.scale())}.
143.1072 +     *
143.1073 +     * @param  augend value to be added to this {@code BigDecimal}.
143.1074 +     * @return {@code this + augend}
143.1075 +     */
143.1076 +    public BigDecimal add(BigDecimal augend) {
143.1077 +        long xs = this.intCompact;
143.1078 +        long ys = augend.intCompact;
143.1079 +        BigInteger fst = (xs != INFLATED) ? null : this.intVal;
143.1080 +        BigInteger snd = (ys != INFLATED) ? null : augend.intVal;
143.1081 +        int rscale = this.scale;
143.1082 +
143.1083 +        long sdiff = (long)rscale - augend.scale;
143.1084 +        if (sdiff != 0) {
143.1085 +            if (sdiff < 0) {
143.1086 +                int raise = checkScale(-sdiff);
143.1087 +                rscale = augend.scale;
143.1088 +                if (xs == INFLATED ||
143.1089 +                    (xs = longMultiplyPowerTen(xs, raise)) == INFLATED)
143.1090 +                    fst = bigMultiplyPowerTen(raise);
143.1091 +            } else {
143.1092 +                int raise = augend.checkScale(sdiff);
143.1093 +                if (ys == INFLATED ||
143.1094 +                    (ys = longMultiplyPowerTen(ys, raise)) == INFLATED)
143.1095 +                    snd = augend.bigMultiplyPowerTen(raise);
143.1096 +            }
143.1097 +        }
143.1098 +        if (xs != INFLATED && ys != INFLATED) {
143.1099 +            long sum = xs + ys;
143.1100 +            // See "Hacker's Delight" section 2-12 for explanation of
143.1101 +            // the overflow test.
143.1102 +            if ( (((sum ^ xs) & (sum ^ ys))) >= 0L) // not overflowed
143.1103 +                return BigDecimal.valueOf(sum, rscale);
143.1104 +        }
143.1105 +        if (fst == null)
143.1106 +            fst = BigInteger.valueOf(xs);
143.1107 +        if (snd == null)
143.1108 +            snd = BigInteger.valueOf(ys);
143.1109 +        BigInteger sum = fst.add(snd);
143.1110 +        return (fst.signum == snd.signum) ?
143.1111 +            new BigDecimal(sum, INFLATED, rscale, 0) :
143.1112 +            new BigDecimal(sum, rscale);
143.1113 +    }
143.1114 +
143.1115 +    /**
143.1116 +     * Returns a {@code BigDecimal} whose value is {@code (this + augend)},
143.1117 +     * with rounding according to the context settings.
143.1118 +     *
143.1119 +     * If either number is zero and the precision setting is nonzero then
143.1120 +     * the other number, rounded if necessary, is used as the result.
143.1121 +     *
143.1122 +     * @param  augend value to be added to this {@code BigDecimal}.
143.1123 +     * @param  mc the context to use.
143.1124 +     * @return {@code this + augend}, rounded as necessary.
143.1125 +     * @throws ArithmeticException if the result is inexact but the
143.1126 +     *         rounding mode is {@code UNNECESSARY}.
143.1127 +     * @since  1.5
143.1128 +     */
143.1129 +    public BigDecimal add(BigDecimal augend, MathContext mc) {
143.1130 +        if (mc.precision == 0)
143.1131 +            return add(augend);
143.1132 +        BigDecimal lhs = this;
143.1133 +
143.1134 +        // Could optimize if values are compact
143.1135 +        this.inflate();
143.1136 +        augend.inflate();
143.1137 +
143.1138 +        // If either number is zero then the other number, rounded and
143.1139 +        // scaled if necessary, is used as the result.
143.1140 +        {
143.1141 +            boolean lhsIsZero = lhs.signum() == 0;
143.1142 +            boolean augendIsZero = augend.signum() == 0;
143.1143 +
143.1144 +            if (lhsIsZero || augendIsZero) {
143.1145 +                int preferredScale = Math.max(lhs.scale(), augend.scale());
143.1146 +                BigDecimal result;
143.1147 +
143.1148 +                // Could use a factory for zero instead of a new object
143.1149 +                if (lhsIsZero && augendIsZero)
143.1150 +                    return new BigDecimal(BigInteger.ZERO, 0, preferredScale, 0);
143.1151 +
143.1152 +                result = lhsIsZero ? doRound(augend, mc) : doRound(lhs, mc);
143.1153 +
143.1154 +                if (result.scale() == preferredScale)
143.1155 +                    return result;
143.1156 +                else if (result.scale() > preferredScale) {
143.1157 +                    BigDecimal scaledResult =
143.1158 +                        new BigDecimal(result.intVal, result.intCompact,
143.1159 +                                       result.scale, 0);
143.1160 +                    scaledResult.stripZerosToMatchScale(preferredScale);
143.1161 +                    return scaledResult;
143.1162 +                } else { // result.scale < preferredScale
143.1163 +                    int precisionDiff = mc.precision - result.precision();
143.1164 +                    int scaleDiff     = preferredScale - result.scale();
143.1165 +
143.1166 +                    if (precisionDiff >= scaleDiff)
143.1167 +                        return result.setScale(preferredScale); // can achieve target scale
143.1168 +                    else
143.1169 +                        return result.setScale(result.scale() + precisionDiff);
143.1170 +                }
143.1171 +            }
143.1172 +        }
143.1173 +
143.1174 +        long padding = (long)lhs.scale - augend.scale;
143.1175 +        if (padding != 0) {        // scales differ; alignment needed
143.1176 +            BigDecimal arg[] = preAlign(lhs, augend, padding, mc);
143.1177 +            matchScale(arg);
143.1178 +            lhs    = arg[0];
143.1179 +            augend = arg[1];
143.1180 +        }
143.1181 +
143.1182 +        BigDecimal d = new BigDecimal(lhs.inflate().add(augend.inflate()),
143.1183 +                                      lhs.scale);
143.1184 +        return doRound(d, mc);
143.1185 +    }
143.1186 +
143.1187 +    /**
143.1188 +     * Returns an array of length two, the sum of whose entries is
143.1189 +     * equal to the rounded sum of the {@code BigDecimal} arguments.
143.1190 +     *
143.1191 +     * <p>If the digit positions of the arguments have a sufficient
143.1192 +     * gap between them, the value smaller in magnitude can be
143.1193 +     * condensed into a {@literal "sticky bit"} and the end result will
143.1194 +     * round the same way <em>if</em> the precision of the final
143.1195 +     * result does not include the high order digit of the small
143.1196 +     * magnitude operand.
143.1197 +     *
143.1198 +     * <p>Note that while strictly speaking this is an optimization,
143.1199 +     * it makes a much wider range of additions practical.
143.1200 +     *
143.1201 +     * <p>This corresponds to a pre-shift operation in a fixed
143.1202 +     * precision floating-point adder; this method is complicated by
143.1203 +     * variable precision of the result as determined by the
143.1204 +     * MathContext.  A more nuanced operation could implement a
143.1205 +     * {@literal "right shift"} on the smaller magnitude operand so
143.1206 +     * that the number of digits of the smaller operand could be
143.1207 +     * reduced even though the significands partially overlapped.
143.1208 +     */
143.1209 +    private BigDecimal[] preAlign(BigDecimal lhs, BigDecimal augend,
143.1210 +                                  long padding, MathContext mc) {
143.1211 +        assert padding != 0;
143.1212 +        BigDecimal big;
143.1213 +        BigDecimal small;
143.1214 +
143.1215 +        if (padding < 0) {     // lhs is big;   augend is small
143.1216 +            big   = lhs;
143.1217 +            small = augend;
143.1218 +        } else {               // lhs is small; augend is big
143.1219 +            big   = augend;
143.1220 +            small = lhs;
143.1221 +        }
143.1222 +
143.1223 +        /*
143.1224 +         * This is the estimated scale of an ulp of the result; it
143.1225 +         * assumes that the result doesn't have a carry-out on a true
143.1226 +         * add (e.g. 999 + 1 => 1000) or any subtractive cancellation
143.1227 +         * on borrowing (e.g. 100 - 1.2 => 98.8)
143.1228 +         */
143.1229 +        long estResultUlpScale = (long)big.scale - big.precision() + mc.precision;
143.1230 +
143.1231 +        /*
143.1232 +         * The low-order digit position of big is big.scale().  This
143.1233 +         * is true regardless of whether big has a positive or
143.1234 +         * negative scale.  The high-order digit position of small is
143.1235 +         * small.scale - (small.precision() - 1).  To do the full
143.1236 +         * condensation, the digit positions of big and small must be
143.1237 +         * disjoint *and* the digit positions of small should not be
143.1238 +         * directly visible in the result.
143.1239 +         */
143.1240 +        long smallHighDigitPos = (long)small.scale - small.precision() + 1;
143.1241 +        if (smallHighDigitPos > big.scale + 2 &&         // big and small disjoint
143.1242 +            smallHighDigitPos > estResultUlpScale + 2) { // small digits not visible
143.1243 +            small = BigDecimal.valueOf(small.signum(),
143.1244 +                                       this.checkScale(Math.max(big.scale, estResultUlpScale) + 3));
143.1245 +        }
143.1246 +
143.1247 +        // Since addition is symmetric, preserving input order in
143.1248 +        // returned operands doesn't matter
143.1249 +        BigDecimal[] result = {big, small};
143.1250 +        return result;
143.1251 +    }
143.1252 +
143.1253 +    /**
143.1254 +     * Returns a {@code BigDecimal} whose value is {@code (this -
143.1255 +     * subtrahend)}, and whose scale is {@code max(this.scale(),
143.1256 +     * subtrahend.scale())}.
143.1257 +     *
143.1258 +     * @param  subtrahend value to be subtracted from this {@code BigDecimal}.
143.1259 +     * @return {@code this - subtrahend}
143.1260 +     */
143.1261 +    public BigDecimal subtract(BigDecimal subtrahend) {
143.1262 +        return add(subtrahend.negate());
143.1263 +    }
143.1264 +
143.1265 +    /**
143.1266 +     * Returns a {@code BigDecimal} whose value is {@code (this - subtrahend)},
143.1267 +     * with rounding according to the context settings.
143.1268 +     *
143.1269 +     * If {@code subtrahend} is zero then this, rounded if necessary, is used as the
143.1270 +     * result.  If this is zero then the result is {@code subtrahend.negate(mc)}.
143.1271 +     *
143.1272 +     * @param  subtrahend value to be subtracted from this {@code BigDecimal}.
143.1273 +     * @param  mc the context to use.
143.1274 +     * @return {@code this - subtrahend}, rounded as necessary.
143.1275 +     * @throws ArithmeticException if the result is inexact but the
143.1276 +     *         rounding mode is {@code UNNECESSARY}.
143.1277 +     * @since  1.5
143.1278 +     */
143.1279 +    public BigDecimal subtract(BigDecimal subtrahend, MathContext mc) {
143.1280 +        BigDecimal nsubtrahend = subtrahend.negate();
143.1281 +        if (mc.precision == 0)
143.1282 +            return add(nsubtrahend);
143.1283 +        // share the special rounding code in add()
143.1284 +        return add(nsubtrahend, mc);
143.1285 +    }
143.1286 +
143.1287 +    /**
143.1288 +     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
143.1289 +     * multiplicand)</tt>, and whose scale is {@code (this.scale() +
143.1290 +     * multiplicand.scale())}.
143.1291 +     *
143.1292 +     * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
143.1293 +     * @return {@code this * multiplicand}
143.1294 +     */
143.1295 +    public BigDecimal multiply(BigDecimal multiplicand) {
143.1296 +        long x = this.intCompact;
143.1297 +        long y = multiplicand.intCompact;
143.1298 +        int productScale = checkScale((long)scale + multiplicand.scale);
143.1299 +
143.1300 +        // Might be able to do a more clever check incorporating the
143.1301 +        // inflated check into the overflow computation.
143.1302 +        if (x != INFLATED && y != INFLATED) {
143.1303 +            /*
143.1304 +             * If the product is not an overflowed value, continue
143.1305 +             * to use the compact representation.  if either of x or y
143.1306 +             * is INFLATED, the product should also be regarded as
143.1307 +             * an overflow. Before using the overflow test suggested in
143.1308 +             * "Hacker's Delight" section 2-12, we perform quick checks
143.1309 +             * using the precision information to see whether the overflow
143.1310 +             * would occur since division is expensive on most CPUs.
143.1311 +             */
143.1312 +            long product = x * y;
143.1313 +            long prec = this.precision() + multiplicand.precision();
143.1314 +            if (prec < 19 || (prec < 21 && (y == 0 || product / y == x)))
143.1315 +                return BigDecimal.valueOf(product, productScale);
143.1316 +            return new BigDecimal(BigInteger.valueOf(x).multiply(y), INFLATED,
143.1317 +                                  productScale, 0);
143.1318 +        }
143.1319 +        BigInteger rb;
143.1320 +        if (x == INFLATED && y == INFLATED)
143.1321 +            rb = this.intVal.multiply(multiplicand.intVal);
143.1322 +        else if (x != INFLATED)
143.1323 +            rb = multiplicand.intVal.multiply(x);
143.1324 +        else
143.1325 +            rb = this.intVal.multiply(y);
143.1326 +        return new BigDecimal(rb, INFLATED, productScale, 0);
143.1327 +    }
143.1328 +
143.1329 +    /**
143.1330 +     * Returns a {@code BigDecimal} whose value is <tt>(this &times;
143.1331 +     * multiplicand)</tt>, with rounding according to the context settings.
143.1332 +     *
143.1333 +     * @param  multiplicand value to be multiplied by this {@code BigDecimal}.
143.1334 +     * @param  mc the context to use.
143.1335 +     * @return {@code this * multiplicand}, rounded as necessary.
143.1336 +     * @throws ArithmeticException if the result is inexact but the
143.1337 +     *         rounding mode is {@code UNNECESSARY}.
143.1338 +     * @since  1.5
143.1339 +     */
143.1340 +    public BigDecimal multiply(BigDecimal multiplicand, MathContext mc) {
143.1341 +        if (mc.precision == 0)
143.1342 +            return multiply(multiplicand);
143.1343 +        return doRound(this.multiply(multiplicand), mc);
143.1344 +    }
143.1345 +
143.1346 +    /**
143.1347 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1348 +     * divisor)}, and whose scale is as specified.  If rounding must
143.1349 +     * be performed to generate a result with the specified scale, the
143.1350 +     * specified rounding mode is applied.
143.1351 +     *
143.1352 +     * <p>The new {@link #divide(BigDecimal, int, RoundingMode)} method
143.1353 +     * should be used in preference to this legacy method.
143.1354 +     *
143.1355 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1356 +     * @param  scale scale of the {@code BigDecimal} quotient to be returned.
143.1357 +     * @param  roundingMode rounding mode to apply.
143.1358 +     * @return {@code this / divisor}
143.1359 +     * @throws ArithmeticException if {@code divisor} is zero,
143.1360 +     *         {@code roundingMode==ROUND_UNNECESSARY} and
143.1361 +     *         the specified scale is insufficient to represent the result
143.1362 +     *         of the division exactly.
143.1363 +     * @throws IllegalArgumentException if {@code roundingMode} does not
143.1364 +     *         represent a valid rounding mode.
143.1365 +     * @see    #ROUND_UP
143.1366 +     * @see    #ROUND_DOWN
143.1367 +     * @see    #ROUND_CEILING
143.1368 +     * @see    #ROUND_FLOOR
143.1369 +     * @see    #ROUND_HALF_UP
143.1370 +     * @see    #ROUND_HALF_DOWN
143.1371 +     * @see    #ROUND_HALF_EVEN
143.1372 +     * @see    #ROUND_UNNECESSARY
143.1373 +     */
143.1374 +    public BigDecimal divide(BigDecimal divisor, int scale, int roundingMode) {
143.1375 +        /*
143.1376 +         * IMPLEMENTATION NOTE: This method *must* return a new object
143.1377 +         * since divideAndRound uses divide to generate a value whose
143.1378 +         * scale is then modified.
143.1379 +         */
143.1380 +        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
143.1381 +            throw new IllegalArgumentException("Invalid rounding mode");
143.1382 +        /*
143.1383 +         * Rescale dividend or divisor (whichever can be "upscaled" to
143.1384 +         * produce correctly scaled quotient).
143.1385 +         * Take care to detect out-of-range scales
143.1386 +         */
143.1387 +        BigDecimal dividend = this;
143.1388 +        if (checkScale((long)scale + divisor.scale) > this.scale)
143.1389 +            dividend = this.setScale(scale + divisor.scale, ROUND_UNNECESSARY);
143.1390 +        else
143.1391 +            divisor = divisor.setScale(checkScale((long)this.scale - scale),
143.1392 +                                       ROUND_UNNECESSARY);
143.1393 +        return divideAndRound(dividend.intCompact, dividend.intVal,
143.1394 +                              divisor.intCompact, divisor.intVal,
143.1395 +                              scale, roundingMode, scale);
143.1396 +    }
143.1397 +
143.1398 +    /**
143.1399 +     * Internally used for division operation. The dividend and divisor are
143.1400 +     * passed both in {@code long} format and {@code BigInteger} format. The
143.1401 +     * returned {@code BigDecimal} object is the quotient whose scale is set to
143.1402 +     * the passed in scale. If the remainder is not zero, it will be rounded
143.1403 +     * based on the passed in roundingMode. Also, if the remainder is zero and
143.1404 +     * the last parameter, i.e. preferredScale is NOT equal to scale, the
143.1405 +     * trailing zeros of the result is stripped to match the preferredScale.
143.1406 +     */
143.1407 +    private static BigDecimal divideAndRound(long ldividend, BigInteger bdividend,
143.1408 +                                             long ldivisor,  BigInteger bdivisor,
143.1409 +                                             int scale, int roundingMode,
143.1410 +                                             int preferredScale) {
143.1411 +        boolean isRemainderZero;       // record remainder is zero or not
143.1412 +        int qsign;                     // quotient sign
143.1413 +        long q = 0, r = 0;             // store quotient & remainder in long
143.1414 +        MutableBigInteger mq = null;   // store quotient
143.1415 +        MutableBigInteger mr = null;   // store remainder
143.1416 +        MutableBigInteger mdivisor = null;
143.1417 +        boolean isLongDivision = (ldividend != INFLATED && ldivisor != INFLATED);
143.1418 +        if (isLongDivision) {
143.1419 +            q = ldividend / ldivisor;
143.1420 +            if (roundingMode == ROUND_DOWN && scale == preferredScale)
143.1421 +                return new BigDecimal(null, q, scale, 0);
143.1422 +            r = ldividend % ldivisor;
143.1423 +            isRemainderZero = (r == 0);
143.1424 +            qsign = ((ldividend < 0) == (ldivisor < 0)) ? 1 : -1;
143.1425 +        } else {
143.1426 +            if (bdividend == null)
143.1427 +                bdividend = BigInteger.valueOf(ldividend);
143.1428 +            // Descend into mutables for faster remainder checks
143.1429 +            MutableBigInteger mdividend = new MutableBigInteger(bdividend.mag);
143.1430 +            mq = new MutableBigInteger();
143.1431 +            if (ldivisor != INFLATED) {
143.1432 +                r = mdividend.divide(ldivisor, mq);
143.1433 +                isRemainderZero = (r == 0);
143.1434 +                qsign = (ldivisor < 0) ? -bdividend.signum : bdividend.signum;
143.1435 +            } else {
143.1436 +                mdivisor = new MutableBigInteger(bdivisor.mag);
143.1437 +                mr = mdividend.divide(mdivisor, mq);
143.1438 +                isRemainderZero = mr.isZero();
143.1439 +                qsign = (bdividend.signum != bdivisor.signum) ? -1 : 1;
143.1440 +            }
143.1441 +        }
143.1442 +        boolean increment = false;
143.1443 +        if (!isRemainderZero) {
143.1444 +            int cmpFracHalf;
143.1445 +            /* Round as appropriate */
143.1446 +            if (roundingMode == ROUND_UNNECESSARY) {  // Rounding prohibited
143.1447 +                throw new ArithmeticException("Rounding necessary");
143.1448 +            } else if (roundingMode == ROUND_UP) {      // Away from zero
143.1449 +                increment = true;
143.1450 +            } else if (roundingMode == ROUND_DOWN) {    // Towards zero
143.1451 +                increment = false;
143.1452 +            } else if (roundingMode == ROUND_CEILING) { // Towards +infinity
143.1453 +                increment = (qsign > 0);
143.1454 +            } else if (roundingMode == ROUND_FLOOR) {   // Towards -infinity
143.1455 +                increment = (qsign < 0);
143.1456 +            } else {
143.1457 +                if (isLongDivision || ldivisor != INFLATED) {
143.1458 +                    if (r <= HALF_LONG_MIN_VALUE || r > HALF_LONG_MAX_VALUE) {
143.1459 +                        cmpFracHalf = 1;    // 2 * r can't fit into long
143.1460 +                    } else {
143.1461 +                        cmpFracHalf = longCompareMagnitude(2 * r, ldivisor);
143.1462 +                    }
143.1463 +                } else {
143.1464 +                    cmpFracHalf = mr.compareHalf(mdivisor);
143.1465 +                }
143.1466 +                if (cmpFracHalf < 0)
143.1467 +                    increment = false;     // We're closer to higher digit
143.1468 +                else if (cmpFracHalf > 0)  // We're closer to lower digit
143.1469 +                    increment = true;
143.1470 +                else if (roundingMode == ROUND_HALF_UP)
143.1471 +                    increment = true;
143.1472 +                else if (roundingMode == ROUND_HALF_DOWN)
143.1473 +                    increment = false;
143.1474 +                else  // roundingMode == ROUND_HALF_EVEN, true iff quotient is odd
143.1475 +                    increment = isLongDivision ? (q & 1L) != 0L : mq.isOdd();
143.1476 +            }
143.1477 +        }
143.1478 +        BigDecimal res;
143.1479 +        if (isLongDivision)
143.1480 +            res = new BigDecimal(null, (increment ? q + qsign : q), scale, 0);
143.1481 +        else {
143.1482 +            if (increment)
143.1483 +                mq.add(MutableBigInteger.ONE);
143.1484 +            res = mq.toBigDecimal(qsign, scale);
143.1485 +        }
143.1486 +        if (isRemainderZero && preferredScale != scale)
143.1487 +            res.stripZerosToMatchScale(preferredScale);
143.1488 +        return res;
143.1489 +    }
143.1490 +
143.1491 +    /**
143.1492 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1493 +     * divisor)}, and whose scale is as specified.  If rounding must
143.1494 +     * be performed to generate a result with the specified scale, the
143.1495 +     * specified rounding mode is applied.
143.1496 +     *
143.1497 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1498 +     * @param  scale scale of the {@code BigDecimal} quotient to be returned.
143.1499 +     * @param  roundingMode rounding mode to apply.
143.1500 +     * @return {@code this / divisor}
143.1501 +     * @throws ArithmeticException if {@code divisor} is zero,
143.1502 +     *         {@code roundingMode==RoundingMode.UNNECESSARY} and
143.1503 +     *         the specified scale is insufficient to represent the result
143.1504 +     *         of the division exactly.
143.1505 +     * @since 1.5
143.1506 +     */
143.1507 +    public BigDecimal divide(BigDecimal divisor, int scale, RoundingMode roundingMode) {
143.1508 +        return divide(divisor, scale, roundingMode.oldMode);
143.1509 +    }
143.1510 +
143.1511 +    /**
143.1512 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1513 +     * divisor)}, and whose scale is {@code this.scale()}.  If
143.1514 +     * rounding must be performed to generate a result with the given
143.1515 +     * scale, the specified rounding mode is applied.
143.1516 +     *
143.1517 +     * <p>The new {@link #divide(BigDecimal, RoundingMode)} method
143.1518 +     * should be used in preference to this legacy method.
143.1519 +     *
143.1520 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1521 +     * @param  roundingMode rounding mode to apply.
143.1522 +     * @return {@code this / divisor}
143.1523 +     * @throws ArithmeticException if {@code divisor==0}, or
143.1524 +     *         {@code roundingMode==ROUND_UNNECESSARY} and
143.1525 +     *         {@code this.scale()} is insufficient to represent the result
143.1526 +     *         of the division exactly.
143.1527 +     * @throws IllegalArgumentException if {@code roundingMode} does not
143.1528 +     *         represent a valid rounding mode.
143.1529 +     * @see    #ROUND_UP
143.1530 +     * @see    #ROUND_DOWN
143.1531 +     * @see    #ROUND_CEILING
143.1532 +     * @see    #ROUND_FLOOR
143.1533 +     * @see    #ROUND_HALF_UP
143.1534 +     * @see    #ROUND_HALF_DOWN
143.1535 +     * @see    #ROUND_HALF_EVEN
143.1536 +     * @see    #ROUND_UNNECESSARY
143.1537 +     */
143.1538 +    public BigDecimal divide(BigDecimal divisor, int roundingMode) {
143.1539 +            return this.divide(divisor, scale, roundingMode);
143.1540 +    }
143.1541 +
143.1542 +    /**
143.1543 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1544 +     * divisor)}, and whose scale is {@code this.scale()}.  If
143.1545 +     * rounding must be performed to generate a result with the given
143.1546 +     * scale, the specified rounding mode is applied.
143.1547 +     *
143.1548 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1549 +     * @param  roundingMode rounding mode to apply.
143.1550 +     * @return {@code this / divisor}
143.1551 +     * @throws ArithmeticException if {@code divisor==0}, or
143.1552 +     *         {@code roundingMode==RoundingMode.UNNECESSARY} and
143.1553 +     *         {@code this.scale()} is insufficient to represent the result
143.1554 +     *         of the division exactly.
143.1555 +     * @since 1.5
143.1556 +     */
143.1557 +    public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) {
143.1558 +        return this.divide(divisor, scale, roundingMode.oldMode);
143.1559 +    }
143.1560 +
143.1561 +    /**
143.1562 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1563 +     * divisor)}, and whose preferred scale is {@code (this.scale() -
143.1564 +     * divisor.scale())}; if the exact quotient cannot be
143.1565 +     * represented (because it has a non-terminating decimal
143.1566 +     * expansion) an {@code ArithmeticException} is thrown.
143.1567 +     *
143.1568 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1569 +     * @throws ArithmeticException if the exact quotient does not have a
143.1570 +     *         terminating decimal expansion
143.1571 +     * @return {@code this / divisor}
143.1572 +     * @since 1.5
143.1573 +     * @author Joseph D. Darcy
143.1574 +     */
143.1575 +    public BigDecimal divide(BigDecimal divisor) {
143.1576 +        /*
143.1577 +         * Handle zero cases first.
143.1578 +         */
143.1579 +        if (divisor.signum() == 0) {   // x/0
143.1580 +            if (this.signum() == 0)    // 0/0
143.1581 +                throw new ArithmeticException("Division undefined");  // NaN
143.1582 +            throw new ArithmeticException("Division by zero");
143.1583 +        }
143.1584 +
143.1585 +        // Calculate preferred scale
143.1586 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
143.1587 +        if (this.signum() == 0)        // 0/y
143.1588 +            return (preferredScale >= 0 &&
143.1589 +                    preferredScale < ZERO_SCALED_BY.length) ?
143.1590 +                ZERO_SCALED_BY[preferredScale] :
143.1591 +                BigDecimal.valueOf(0, preferredScale);
143.1592 +        else {
143.1593 +            this.inflate();
143.1594 +            divisor.inflate();
143.1595 +            /*
143.1596 +             * If the quotient this/divisor has a terminating decimal
143.1597 +             * expansion, the expansion can have no more than
143.1598 +             * (a.precision() + ceil(10*b.precision)/3) digits.
143.1599 +             * Therefore, create a MathContext object with this
143.1600 +             * precision and do a divide with the UNNECESSARY rounding
143.1601 +             * mode.
143.1602 +             */
143.1603 +            MathContext mc = new MathContext( (int)Math.min(this.precision() +
143.1604 +                                                            (long)Math.ceil(10.0*divisor.precision()/3.0),
143.1605 +                                                            Integer.MAX_VALUE),
143.1606 +                                              RoundingMode.UNNECESSARY);
143.1607 +            BigDecimal quotient;
143.1608 +            try {
143.1609 +                quotient = this.divide(divisor, mc);
143.1610 +            } catch (ArithmeticException e) {
143.1611 +                throw new ArithmeticException("Non-terminating decimal expansion; " +
143.1612 +                                              "no exact representable decimal result.");
143.1613 +            }
143.1614 +
143.1615 +            int quotientScale = quotient.scale();
143.1616 +
143.1617 +            // divide(BigDecimal, mc) tries to adjust the quotient to
143.1618 +            // the desired one by removing trailing zeros; since the
143.1619 +            // exact divide method does not have an explicit digit
143.1620 +            // limit, we can add zeros too.
143.1621 +
143.1622 +            if (preferredScale > quotientScale)
143.1623 +                return quotient.setScale(preferredScale, ROUND_UNNECESSARY);
143.1624 +
143.1625 +            return quotient;
143.1626 +        }
143.1627 +    }
143.1628 +
143.1629 +    /**
143.1630 +     * Returns a {@code BigDecimal} whose value is {@code (this /
143.1631 +     * divisor)}, with rounding according to the context settings.
143.1632 +     *
143.1633 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1634 +     * @param  mc the context to use.
143.1635 +     * @return {@code this / divisor}, rounded as necessary.
143.1636 +     * @throws ArithmeticException if the result is inexact but the
143.1637 +     *         rounding mode is {@code UNNECESSARY} or
143.1638 +     *         {@code mc.precision == 0} and the quotient has a
143.1639 +     *         non-terminating decimal expansion.
143.1640 +     * @since  1.5
143.1641 +     */
143.1642 +    public BigDecimal divide(BigDecimal divisor, MathContext mc) {
143.1643 +        int mcp = mc.precision;
143.1644 +        if (mcp == 0)
143.1645 +            return divide(divisor);
143.1646 +
143.1647 +        BigDecimal dividend = this;
143.1648 +        long preferredScale = (long)dividend.scale - divisor.scale;
143.1649 +        // Now calculate the answer.  We use the existing
143.1650 +        // divide-and-round method, but as this rounds to scale we have
143.1651 +        // to normalize the values here to achieve the desired result.
143.1652 +        // For x/y we first handle y=0 and x=0, and then normalize x and
143.1653 +        // y to give x' and y' with the following constraints:
143.1654 +        //   (a) 0.1 <= x' < 1
143.1655 +        //   (b)  x' <= y' < 10*x'
143.1656 +        // Dividing x'/y' with the required scale set to mc.precision then
143.1657 +        // will give a result in the range 0.1 to 1 rounded to exactly
143.1658 +        // the right number of digits (except in the case of a result of
143.1659 +        // 1.000... which can arise when x=y, or when rounding overflows
143.1660 +        // The 1.000... case will reduce properly to 1.
143.1661 +        if (divisor.signum() == 0) {      // x/0
143.1662 +            if (dividend.signum() == 0)    // 0/0
143.1663 +                throw new ArithmeticException("Division undefined");  // NaN
143.1664 +            throw new ArithmeticException("Division by zero");
143.1665 +        }
143.1666 +        if (dividend.signum() == 0)        // 0/y
143.1667 +            return new BigDecimal(BigInteger.ZERO, 0,
143.1668 +                                  saturateLong(preferredScale), 1);
143.1669 +
143.1670 +        // Normalize dividend & divisor so that both fall into [0.1, 0.999...]
143.1671 +        int xscale = dividend.precision();
143.1672 +        int yscale = divisor.precision();
143.1673 +        dividend = new BigDecimal(dividend.intVal, dividend.intCompact,
143.1674 +                                  xscale, xscale);
143.1675 +        divisor = new BigDecimal(divisor.intVal, divisor.intCompact,
143.1676 +                                 yscale, yscale);
143.1677 +        if (dividend.compareMagnitude(divisor) > 0) // satisfy constraint (b)
143.1678 +            yscale = divisor.scale -= 1;            // [that is, divisor *= 10]
143.1679 +
143.1680 +        // In order to find out whether the divide generates the exact result,
143.1681 +        // we avoid calling the above divide method. 'quotient' holds the
143.1682 +        // return BigDecimal object whose scale will be set to 'scl'.
143.1683 +        BigDecimal quotient;
143.1684 +        int scl = checkScale(preferredScale + yscale - xscale + mcp);
143.1685 +        if (checkScale((long)mcp + yscale) > xscale)
143.1686 +            dividend = dividend.setScale(mcp + yscale, ROUND_UNNECESSARY);
143.1687 +        else
143.1688 +            divisor = divisor.setScale(checkScale((long)xscale - mcp),
143.1689 +                                       ROUND_UNNECESSARY);
143.1690 +        quotient = divideAndRound(dividend.intCompact, dividend.intVal,
143.1691 +                                  divisor.intCompact, divisor.intVal,
143.1692 +                                  scl, mc.roundingMode.oldMode,
143.1693 +                                  checkScale(preferredScale));
143.1694 +        // doRound, here, only affects 1000000000 case.
143.1695 +        quotient = doRound(quotient, mc);
143.1696 +
143.1697 +        return quotient;
143.1698 +    }
143.1699 +
143.1700 +    /**
143.1701 +     * Returns a {@code BigDecimal} whose value is the integer part
143.1702 +     * of the quotient {@code (this / divisor)} rounded down.  The
143.1703 +     * preferred scale of the result is {@code (this.scale() -
143.1704 +     * divisor.scale())}.
143.1705 +     *
143.1706 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1707 +     * @return The integer part of {@code this / divisor}.
143.1708 +     * @throws ArithmeticException if {@code divisor==0}
143.1709 +     * @since  1.5
143.1710 +     */
143.1711 +    public BigDecimal divideToIntegralValue(BigDecimal divisor) {
143.1712 +        // Calculate preferred scale
143.1713 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
143.1714 +        if (this.compareMagnitude(divisor) < 0) {
143.1715 +            // much faster when this << divisor
143.1716 +            return BigDecimal.valueOf(0, preferredScale);
143.1717 +        }
143.1718 +
143.1719 +        if(this.signum() == 0 && divisor.signum() != 0)
143.1720 +            return this.setScale(preferredScale, ROUND_UNNECESSARY);
143.1721 +
143.1722 +        // Perform a divide with enough digits to round to a correct
143.1723 +        // integer value; then remove any fractional digits
143.1724 +
143.1725 +        int maxDigits = (int)Math.min(this.precision() +
143.1726 +                                      (long)Math.ceil(10.0*divisor.precision()/3.0) +
143.1727 +                                      Math.abs((long)this.scale() - divisor.scale()) + 2,
143.1728 +                                      Integer.MAX_VALUE);
143.1729 +        BigDecimal quotient = this.divide(divisor, new MathContext(maxDigits,
143.1730 +                                                                   RoundingMode.DOWN));
143.1731 +        if (quotient.scale > 0) {
143.1732 +            quotient = quotient.setScale(0, RoundingMode.DOWN);
143.1733 +            quotient.stripZerosToMatchScale(preferredScale);
143.1734 +        }
143.1735 +
143.1736 +        if (quotient.scale < preferredScale) {
143.1737 +            // pad with zeros if necessary
143.1738 +            quotient = quotient.setScale(preferredScale, ROUND_UNNECESSARY);
143.1739 +        }
143.1740 +        return quotient;
143.1741 +    }
143.1742 +
143.1743 +    /**
143.1744 +     * Returns a {@code BigDecimal} whose value is the integer part
143.1745 +     * of {@code (this / divisor)}.  Since the integer part of the
143.1746 +     * exact quotient does not depend on the rounding mode, the
143.1747 +     * rounding mode does not affect the values returned by this
143.1748 +     * method.  The preferred scale of the result is
143.1749 +     * {@code (this.scale() - divisor.scale())}.  An
143.1750 +     * {@code ArithmeticException} is thrown if the integer part of
143.1751 +     * the exact quotient needs more than {@code mc.precision}
143.1752 +     * digits.
143.1753 +     *
143.1754 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1755 +     * @param  mc the context to use.
143.1756 +     * @return The integer part of {@code this / divisor}.
143.1757 +     * @throws ArithmeticException if {@code divisor==0}
143.1758 +     * @throws ArithmeticException if {@code mc.precision} {@literal >} 0 and the result
143.1759 +     *         requires a precision of more than {@code mc.precision} digits.
143.1760 +     * @since  1.5
143.1761 +     * @author Joseph D. Darcy
143.1762 +     */
143.1763 +    public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) {
143.1764 +        if (mc.precision == 0 ||                        // exact result
143.1765 +            (this.compareMagnitude(divisor) < 0) )      // zero result
143.1766 +            return divideToIntegralValue(divisor);
143.1767 +
143.1768 +        // Calculate preferred scale
143.1769 +        int preferredScale = saturateLong((long)this.scale - divisor.scale);
143.1770 +
143.1771 +        /*
143.1772 +         * Perform a normal divide to mc.precision digits.  If the
143.1773 +         * remainder has absolute value less than the divisor, the
143.1774 +         * integer portion of the quotient fits into mc.precision
143.1775 +         * digits.  Next, remove any fractional digits from the
143.1776 +         * quotient and adjust the scale to the preferred value.
143.1777 +         */
143.1778 +        BigDecimal result = this.
143.1779 +            divide(divisor, new MathContext(mc.precision, RoundingMode.DOWN));
143.1780 +
143.1781 +        if (result.scale() < 0) {
143.1782 +            /*
143.1783 +             * Result is an integer. See if quotient represents the
143.1784 +             * full integer portion of the exact quotient; if it does,
143.1785 +             * the computed remainder will be less than the divisor.
143.1786 +             */
143.1787 +            BigDecimal product = result.multiply(divisor);
143.1788 +            // If the quotient is the full integer value,
143.1789 +            // |dividend-product| < |divisor|.
143.1790 +            if (this.subtract(product).compareMagnitude(divisor) >= 0) {
143.1791 +                throw new ArithmeticException("Division impossible");
143.1792 +            }
143.1793 +        } else if (result.scale() > 0) {
143.1794 +            /*
143.1795 +             * Integer portion of quotient will fit into precision
143.1796 +             * digits; recompute quotient to scale 0 to avoid double
143.1797 +             * rounding and then try to adjust, if necessary.
143.1798 +             */
143.1799 +            result = result.setScale(0, RoundingMode.DOWN);
143.1800 +        }
143.1801 +        // else result.scale() == 0;
143.1802 +
143.1803 +        int precisionDiff;
143.1804 +        if ((preferredScale > result.scale()) &&
143.1805 +            (precisionDiff = mc.precision - result.precision()) > 0) {
143.1806 +            return result.setScale(result.scale() +
143.1807 +                                   Math.min(precisionDiff, preferredScale - result.scale) );
143.1808 +        } else {
143.1809 +            result.stripZerosToMatchScale(preferredScale);
143.1810 +            return result;
143.1811 +        }
143.1812 +    }
143.1813 +
143.1814 +    /**
143.1815 +     * Returns a {@code BigDecimal} whose value is {@code (this % divisor)}.
143.1816 +     *
143.1817 +     * <p>The remainder is given by
143.1818 +     * {@code this.subtract(this.divideToIntegralValue(divisor).multiply(divisor))}.
143.1819 +     * Note that this is not the modulo operation (the result can be
143.1820 +     * negative).
143.1821 +     *
143.1822 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1823 +     * @return {@code this % divisor}.
143.1824 +     * @throws ArithmeticException if {@code divisor==0}
143.1825 +     * @since  1.5
143.1826 +     */
143.1827 +    public BigDecimal remainder(BigDecimal divisor) {
143.1828 +        BigDecimal divrem[] = this.divideAndRemainder(divisor);
143.1829 +        return divrem[1];
143.1830 +    }
143.1831 +
143.1832 +
143.1833 +    /**
143.1834 +     * Returns a {@code BigDecimal} whose value is {@code (this %
143.1835 +     * divisor)}, with rounding according to the context settings.
143.1836 +     * The {@code MathContext} settings affect the implicit divide
143.1837 +     * used to compute the remainder.  The remainder computation
143.1838 +     * itself is by definition exact.  Therefore, the remainder may
143.1839 +     * contain more than {@code mc.getPrecision()} digits.
143.1840 +     *
143.1841 +     * <p>The remainder is given by
143.1842 +     * {@code this.subtract(this.divideToIntegralValue(divisor,
143.1843 +     * mc).multiply(divisor))}.  Note that this is not the modulo
143.1844 +     * operation (the result can be negative).
143.1845 +     *
143.1846 +     * @param  divisor value by which this {@code BigDecimal} is to be divided.
143.1847 +     * @param  mc the context to use.
143.1848 +     * @return {@code this % divisor}, rounded as necessary.
143.1849 +     * @throws ArithmeticException if {@code divisor==0}
143.1850 +     * @throws ArithmeticException if the result is inexact but the
143.1851 +     *         rounding mode is {@code UNNECESSARY}, or {@code mc.precision}
143.1852 +     *         {@literal >} 0 and the result of {@code this.divideToIntgralValue(divisor)} would
143.1853 +     *         require a precision of more than {@code mc.precision} digits.
143.1854 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
143.1855 +     * @since  1.5
143.1856 +     */
143.1857 +    public BigDecimal remainder(BigDecimal divisor, MathContext mc) {
143.1858 +        BigDecimal divrem[] = this.divideAndRemainder(divisor, mc);
143.1859 +        return divrem[1];
143.1860 +    }
143.1861 +
143.1862 +    /**
143.1863 +     * Returns a two-element {@code BigDecimal} array containing the
143.1864 +     * result of {@code divideToIntegralValue} followed by the result of
143.1865 +     * {@code remainder} on the two operands.
143.1866 +     *
143.1867 +     * <p>Note that if both the integer quotient and remainder are
143.1868 +     * needed, this method is faster than using the
143.1869 +     * {@code divideToIntegralValue} and {@code remainder} methods
143.1870 +     * separately because the division need only be carried out once.
143.1871 +     *
143.1872 +     * @param  divisor value by which this {@code BigDecimal} is to be divided,
143.1873 +     *         and the remainder computed.
143.1874 +     * @return a two element {@code BigDecimal} array: the quotient
143.1875 +     *         (the result of {@code divideToIntegralValue}) is the initial element
143.1876 +     *         and the remainder is the final element.
143.1877 +     * @throws ArithmeticException if {@code divisor==0}
143.1878 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
143.1879 +     * @see    #remainder(java.math.BigDecimal, java.math.MathContext)
143.1880 +     * @since  1.5
143.1881 +     */
143.1882 +    public BigDecimal[] divideAndRemainder(BigDecimal divisor) {
143.1883 +        // we use the identity  x = i * y + r to determine r
143.1884 +        BigDecimal[] result = new BigDecimal[2];
143.1885 +
143.1886 +        result[0] = this.divideToIntegralValue(divisor);
143.1887 +        result[1] = this.subtract(result[0].multiply(divisor));
143.1888 +        return result;
143.1889 +    }
143.1890 +
143.1891 +    /**
143.1892 +     * Returns a two-element {@code BigDecimal} array containing the
143.1893 +     * result of {@code divideToIntegralValue} followed by the result of
143.1894 +     * {@code remainder} on the two operands calculated with rounding
143.1895 +     * according to the context settings.
143.1896 +     *
143.1897 +     * <p>Note that if both the integer quotient and remainder are
143.1898 +     * needed, this method is faster than using the
143.1899 +     * {@code divideToIntegralValue} and {@code remainder} methods
143.1900 +     * separately because the division need only be carried out once.
143.1901 +     *
143.1902 +     * @param  divisor value by which this {@code BigDecimal} is to be divided,
143.1903 +     *         and the remainder computed.
143.1904 +     * @param  mc the context to use.
143.1905 +     * @return a two element {@code BigDecimal} array: the quotient
143.1906 +     *         (the result of {@code divideToIntegralValue}) is the
143.1907 +     *         initial element and the remainder is the final element.
143.1908 +     * @throws ArithmeticException if {@code divisor==0}
143.1909 +     * @throws ArithmeticException if the result is inexact but the
143.1910 +     *         rounding mode is {@code UNNECESSARY}, or {@code mc.precision}
143.1911 +     *         {@literal >} 0 and the result of {@code this.divideToIntgralValue(divisor)} would
143.1912 +     *         require a precision of more than {@code mc.precision} digits.
143.1913 +     * @see    #divideToIntegralValue(java.math.BigDecimal, java.math.MathContext)
143.1914 +     * @see    #remainder(java.math.BigDecimal, java.math.MathContext)
143.1915 +     * @since  1.5
143.1916 +     */
143.1917 +    public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) {
143.1918 +        if (mc.precision == 0)
143.1919 +            return divideAndRemainder(divisor);
143.1920 +
143.1921 +        BigDecimal[] result = new BigDecimal[2];
143.1922 +        BigDecimal lhs = this;
143.1923 +
143.1924 +        result[0] = lhs.divideToIntegralValue(divisor, mc);
143.1925 +        result[1] = lhs.subtract(result[0].multiply(divisor));
143.1926 +        return result;
143.1927 +    }
143.1928 +
143.1929 +    /**
143.1930 +     * Returns a {@code BigDecimal} whose value is
143.1931 +     * <tt>(this<sup>n</sup>)</tt>, The power is computed exactly, to
143.1932 +     * unlimited precision.
143.1933 +     *
143.1934 +     * <p>The parameter {@code n} must be in the range 0 through
143.1935 +     * 999999999, inclusive.  {@code ZERO.pow(0)} returns {@link
143.1936 +     * #ONE}.
143.1937 +     *
143.1938 +     * Note that future releases may expand the allowable exponent
143.1939 +     * range of this method.
143.1940 +     *
143.1941 +     * @param  n power to raise this {@code BigDecimal} to.
143.1942 +     * @return <tt>this<sup>n</sup></tt>
143.1943 +     * @throws ArithmeticException if {@code n} is out of range.
143.1944 +     * @since  1.5
143.1945 +     */
143.1946 +    public BigDecimal pow(int n) {
143.1947 +        if (n < 0 || n > 999999999)
143.1948 +            throw new ArithmeticException("Invalid operation");
143.1949 +        // No need to calculate pow(n) if result will over/underflow.
143.1950 +        // Don't attempt to support "supernormal" numbers.
143.1951 +        int newScale = checkScale((long)scale * n);
143.1952 +        this.inflate();
143.1953 +        return new BigDecimal(intVal.pow(n), newScale);
143.1954 +    }
143.1955 +
143.1956 +
143.1957 +    /**
143.1958 +     * Returns a {@code BigDecimal} whose value is
143.1959 +     * <tt>(this<sup>n</sup>)</tt>.  The current implementation uses
143.1960 +     * the core algorithm defined in ANSI standard X3.274-1996 with
143.1961 +     * rounding according to the context settings.  In general, the
143.1962 +     * returned numerical value is within two ulps of the exact
143.1963 +     * numerical value for the chosen precision.  Note that future
143.1964 +     * releases may use a different algorithm with a decreased
143.1965 +     * allowable error bound and increased allowable exponent range.
143.1966 +     *
143.1967 +     * <p>The X3.274-1996 algorithm is:
143.1968 +     *
143.1969 +     * <ul>
143.1970 +     * <li> An {@code ArithmeticException} exception is thrown if
143.1971 +     *  <ul>
143.1972 +     *    <li>{@code abs(n) > 999999999}
143.1973 +     *    <li>{@code mc.precision == 0} and {@code n < 0}
143.1974 +     *    <li>{@code mc.precision > 0} and {@code n} has more than
143.1975 +     *    {@code mc.precision} decimal digits
143.1976 +     *  </ul>
143.1977 +     *
143.1978 +     * <li> if {@code n} is zero, {@link #ONE} is returned even if
143.1979 +     * {@code this} is zero, otherwise
143.1980 +     * <ul>
143.1981 +     *   <li> if {@code n} is positive, the result is calculated via
143.1982 +     *   the repeated squaring technique into a single accumulator.
143.1983 +     *   The individual multiplications with the accumulator use the
143.1984 +     *   same math context settings as in {@code mc} except for a
143.1985 +     *   precision increased to {@code mc.precision + elength + 1}
143.1986 +     *   where {@code elength} is the number of decimal digits in
143.1987 +     *   {@code n}.
143.1988 +     *
143.1989 +     *   <li> if {@code n} is negative, the result is calculated as if
143.1990 +     *   {@code n} were positive; this value is then divided into one
143.1991 +     *   using the working precision specified above.
143.1992 +     *
143.1993 +     *   <li> The final value from either the positive or negative case
143.1994 +     *   is then rounded to the destination precision.
143.1995 +     *   </ul>
143.1996 +     * </ul>
143.1997 +     *
143.1998 +     * @param  n power to raise this {@code BigDecimal} to.
143.1999 +     * @param  mc the context to use.
143.2000 +     * @return <tt>this<sup>n</sup></tt> using the ANSI standard X3.274-1996
143.2001 +     *         algorithm
143.2002 +     * @throws ArithmeticException if the result is inexact but the
143.2003 +     *         rounding mode is {@code UNNECESSARY}, or {@code n} is out
143.2004 +     *         of range.
143.2005 +     * @since  1.5
143.2006 +     */
143.2007 +    public BigDecimal pow(int n, MathContext mc) {
143.2008 +        if (mc.precision == 0)
143.2009 +            return pow(n);
143.2010 +        if (n < -999999999 || n > 999999999)
143.2011 +            throw new ArithmeticException("Invalid operation");
143.2012 +        if (n == 0)
143.2013 +            return ONE;                      // x**0 == 1 in X3.274
143.2014 +        this.inflate();
143.2015 +        BigDecimal lhs = this;
143.2016 +        MathContext workmc = mc;           // working settings
143.2017 +        int mag = Math.abs(n);               // magnitude of n
143.2018 +        if (mc.precision > 0) {
143.2019 +
143.2020 +            int elength = longDigitLength(mag); // length of n in digits
143.2021 +            if (elength > mc.precision)        // X3.274 rule
143.2022 +                throw new ArithmeticException("Invalid operation");
143.2023 +            workmc = new MathContext(mc.precision + elength + 1,
143.2024 +                                      mc.roundingMode);
143.2025 +        }
143.2026 +        // ready to carry out power calculation...
143.2027 +        BigDecimal acc = ONE;           // accumulator
143.2028 +        boolean seenbit = false;        // set once we've seen a 1-bit
143.2029 +        for (int i=1;;i++) {            // for each bit [top bit ignored]
143.2030 +            mag += mag;                 // shift left 1 bit
143.2031 +            if (mag < 0) {              // top bit is set
143.2032 +                seenbit = true;         // OK, we're off
143.2033 +                acc = acc.multiply(lhs, workmc); // acc=acc*x
143.2034 +            }
143.2035 +            if (i == 31)
143.2036 +                break;                  // that was the last bit
143.2037 +            if (seenbit)
143.2038 +                acc=acc.multiply(acc, workmc);   // acc=acc*acc [square]
143.2039 +                // else (!seenbit) no point in squaring ONE
143.2040 +        }
143.2041 +        // if negative n, calculate the reciprocal using working precision
143.2042 +        if (n<0)                          // [hence mc.precision>0]
143.2043 +            acc=ONE.divide(acc, workmc);
143.2044 +        // round to final precision and strip zeros
143.2045 +        return doRound(acc, mc);
143.2046 +    }
143.2047 +
143.2048 +    /**
143.2049 +     * Returns a {@code BigDecimal} whose value is the absolute value
143.2050 +     * of this {@code BigDecimal}, and whose scale is
143.2051 +     * {@code this.scale()}.
143.2052 +     *
143.2053 +     * @return {@code abs(this)}
143.2054 +     */
143.2055 +    public BigDecimal abs() {
143.2056 +        return (signum() < 0 ? negate() : this);
143.2057 +    }
143.2058 +
143.2059 +    /**
143.2060 +     * Returns a {@code BigDecimal} whose value is the absolute value
143.2061 +     * of this {@code BigDecimal}, with rounding according to the
143.2062 +     * context settings.
143.2063 +     *
143.2064 +     * @param mc the context to use.
143.2065 +     * @return {@code abs(this)}, rounded as necessary.
143.2066 +     * @throws ArithmeticException if the result is inexact but the
143.2067 +     *         rounding mode is {@code UNNECESSARY}.
143.2068 +     * @since 1.5
143.2069 +     */
143.2070 +    public BigDecimal abs(MathContext mc) {
143.2071 +        return (signum() < 0 ? negate(mc) : plus(mc));
143.2072 +    }
143.2073 +
143.2074 +    /**
143.2075 +     * Returns a {@code BigDecimal} whose value is {@code (-this)},
143.2076 +     * and whose scale is {@code this.scale()}.
143.2077 +     *
143.2078 +     * @return {@code -this}.
143.2079 +     */
143.2080 +    public BigDecimal negate() {
143.2081 +        BigDecimal result;
143.2082 +        if (intCompact != INFLATED)
143.2083 +            result = BigDecimal.valueOf(-intCompact, scale);
143.2084 +        else {
143.2085 +            result = new BigDecimal(intVal.negate(), scale);
143.2086 +            result.precision = precision;
143.2087 +        }
143.2088 +        return result;
143.2089 +    }
143.2090 +
143.2091 +    /**
143.2092 +     * Returns a {@code BigDecimal} whose value is {@code (-this)},
143.2093 +     * with rounding according to the context settings.
143.2094 +     *
143.2095 +     * @param mc the context to use.
143.2096 +     * @return {@code -this}, rounded as necessary.
143.2097 +     * @throws ArithmeticException if the result is inexact but the
143.2098 +     *         rounding mode is {@code UNNECESSARY}.
143.2099 +     * @since  1.5
143.2100 +     */
143.2101 +    public BigDecimal negate(MathContext mc) {
143.2102 +        return negate().plus(mc);
143.2103 +    }
143.2104 +
143.2105 +    /**
143.2106 +     * Returns a {@code BigDecimal} whose value is {@code (+this)}, and whose
143.2107 +     * scale is {@code this.scale()}.
143.2108 +     *
143.2109 +     * <p>This method, which simply returns this {@code BigDecimal}
143.2110 +     * is included for symmetry with the unary minus method {@link
143.2111 +     * #negate()}.
143.2112 +     *
143.2113 +     * @return {@code this}.
143.2114 +     * @see #negate()
143.2115 +     * @since  1.5
143.2116 +     */
143.2117 +    public BigDecimal plus() {
143.2118 +        return this;
143.2119 +    }
143.2120 +
143.2121 +    /**
143.2122 +     * Returns a {@code BigDecimal} whose value is {@code (+this)},
143.2123 +     * with rounding according to the context settings.
143.2124 +     *
143.2125 +     * <p>The effect of this method is identical to that of the {@link
143.2126 +     * #round(MathContext)} method.
143.2127 +     *
143.2128 +     * @param mc the context to use.
143.2129 +     * @return {@code this}, rounded as necessary.  A zero result will
143.2130 +     *         have a scale of 0.
143.2131 +     * @throws ArithmeticException if the result is inexact but the
143.2132 +     *         rounding mode is {@code UNNECESSARY}.
143.2133 +     * @see    #round(MathContext)
143.2134 +     * @since  1.5
143.2135 +     */
143.2136 +    public BigDecimal plus(MathContext mc) {
143.2137 +        if (mc.precision == 0)                 // no rounding please
143.2138 +            return this;
143.2139 +        return doRound(this, mc);
143.2140 +    }
143.2141 +
143.2142 +    /**
143.2143 +     * Returns the signum function of this {@code BigDecimal}.
143.2144 +     *
143.2145 +     * @return -1, 0, or 1 as the value of this {@code BigDecimal}
143.2146 +     *         is negative, zero, or positive.
143.2147 +     */
143.2148 +    public int signum() {
143.2149 +        return (intCompact != INFLATED)?
143.2150 +            Long.signum(intCompact):
143.2151 +            intVal.signum();
143.2152 +    }
143.2153 +
143.2154 +    /**
143.2155 +     * Returns the <i>scale</i> of this {@code BigDecimal}.  If zero
143.2156 +     * or positive, the scale is the number of digits to the right of
143.2157 +     * the decimal point.  If negative, the unscaled value of the
143.2158 +     * number is multiplied by ten to the power of the negation of the
143.2159 +     * scale.  For example, a scale of {@code -3} means the unscaled
143.2160 +     * value is multiplied by 1000.
143.2161 +     *
143.2162 +     * @return the scale of this {@code BigDecimal}.
143.2163 +     */
143.2164 +    public int scale() {
143.2165 +        return scale;
143.2166 +    }
143.2167 +
143.2168 +    /**
143.2169 +     * Returns the <i>precision</i> of this {@code BigDecimal}.  (The
143.2170 +     * precision is the number of digits in the unscaled value.)
143.2171 +     *
143.2172 +     * <p>The precision of a zero value is 1.
143.2173 +     *
143.2174 +     * @return the precision of this {@code BigDecimal}.
143.2175 +     * @since  1.5
143.2176 +     */
143.2177 +    public int precision() {
143.2178 +        int result = precision;
143.2179 +        if (result == 0) {
143.2180 +            long s = intCompact;
143.2181 +            if (s != INFLATED)
143.2182 +                result = longDigitLength(s);
143.2183 +            else
143.2184 +                result = bigDigitLength(inflate());
143.2185 +            precision = result;
143.2186 +        }
143.2187 +        return result;
143.2188 +    }
143.2189 +
143.2190 +
143.2191 +    /**
143.2192 +     * Returns a {@code BigInteger} whose value is the <i>unscaled
143.2193 +     * value</i> of this {@code BigDecimal}.  (Computes <tt>(this *
143.2194 +     * 10<sup>this.scale()</sup>)</tt>.)
143.2195 +     *
143.2196 +     * @return the unscaled value of this {@code BigDecimal}.
143.2197 +     * @since  1.2
143.2198 +     */
143.2199 +    public BigInteger unscaledValue() {
143.2200 +        return this.inflate();
143.2201 +    }
143.2202 +
143.2203 +    // Rounding Modes
143.2204 +
143.2205 +    /**
143.2206 +     * Rounding mode to round away from zero.  Always increments the
143.2207 +     * digit prior to a nonzero discarded fraction.  Note that this rounding
143.2208 +     * mode never decreases the magnitude of the calculated value.
143.2209 +     */
143.2210 +    public final static int ROUND_UP =           0;
143.2211 +
143.2212 +    /**
143.2213 +     * Rounding mode to round towards zero.  Never increments the digit
143.2214 +     * prior to a discarded fraction (i.e., truncates).  Note that this
143.2215 +     * rounding mode never increases the magnitude of the calculated value.
143.2216 +     */
143.2217 +    public final static int ROUND_DOWN =         1;
143.2218 +
143.2219 +    /**
143.2220 +     * Rounding mode to round towards positive infinity.  If the
143.2221 +     * {@code BigDecimal} is positive, behaves as for
143.2222 +     * {@code ROUND_UP}; if negative, behaves as for
143.2223 +     * {@code ROUND_DOWN}.  Note that this rounding mode never
143.2224 +     * decreases the calculated value.
143.2225 +     */
143.2226 +    public final static int ROUND_CEILING =      2;
143.2227 +
143.2228 +    /**
143.2229 +     * Rounding mode to round towards negative infinity.  If the
143.2230 +     * {@code BigDecimal} is positive, behave as for
143.2231 +     * {@code ROUND_DOWN}; if negative, behave as for
143.2232 +     * {@code ROUND_UP}.  Note that this rounding mode never
143.2233 +     * increases the calculated value.
143.2234 +     */
143.2235 +    public final static int ROUND_FLOOR =        3;
143.2236 +
143.2237 +    /**
143.2238 +     * Rounding mode to round towards {@literal "nearest neighbor"}
143.2239 +     * unless both neighbors are equidistant, in which case round up.
143.2240 +     * Behaves as for {@code ROUND_UP} if the discarded fraction is
143.2241 +     * &ge; 0.5; otherwise, behaves as for {@code ROUND_DOWN}.  Note
143.2242 +     * that this is the rounding mode that most of us were taught in
143.2243 +     * grade school.
143.2244 +     */
143.2245 +    public final static int ROUND_HALF_UP =      4;
143.2246 +
143.2247 +    /**
143.2248 +     * Rounding mode to round towards {@literal "nearest neighbor"}
143.2249 +     * unless both neighbors are equidistant, in which case round
143.2250 +     * down.  Behaves as for {@code ROUND_UP} if the discarded
143.2251 +     * fraction is {@literal >} 0.5; otherwise, behaves as for
143.2252 +     * {@code ROUND_DOWN}.
143.2253 +     */
143.2254 +    public final static int ROUND_HALF_DOWN =    5;
143.2255 +
143.2256 +    /**
143.2257 +     * Rounding mode to round towards the {@literal "nearest neighbor"}
143.2258 +     * unless both neighbors are equidistant, in which case, round
143.2259 +     * towards the even neighbor.  Behaves as for
143.2260 +     * {@code ROUND_HALF_UP} if the digit to the left of the
143.2261 +     * discarded fraction is odd; behaves as for
143.2262 +     * {@code ROUND_HALF_DOWN} if it's even.  Note that this is the
143.2263 +     * rounding mode that minimizes cumulative error when applied
143.2264 +     * repeatedly over a sequence of calculations.
143.2265 +     */
143.2266 +    public final static int ROUND_HALF_EVEN =    6;
143.2267 +
143.2268 +    /**
143.2269 +     * Rounding mode to assert that the requested operation has an exact
143.2270 +     * result, hence no rounding is necessary.  If this rounding mode is
143.2271 +     * specified on an operation that yields an inexact result, an
143.2272 +     * {@code ArithmeticException} is thrown.
143.2273 +     */
143.2274 +    public final static int ROUND_UNNECESSARY =  7;
143.2275 +
143.2276 +
143.2277 +    // Scaling/Rounding Operations
143.2278 +
143.2279 +    /**
143.2280 +     * Returns a {@code BigDecimal} rounded according to the
143.2281 +     * {@code MathContext} settings.  If the precision setting is 0 then
143.2282 +     * no rounding takes place.
143.2283 +     *
143.2284 +     * <p>The effect of this method is identical to that of the
143.2285 +     * {@link #plus(MathContext)} method.
143.2286 +     *
143.2287 +     * @param mc the context to use.
143.2288 +     * @return a {@code BigDecimal} rounded according to the
143.2289 +     *         {@code MathContext} settings.
143.2290 +     * @throws ArithmeticException if the rounding mode is
143.2291 +     *         {@code UNNECESSARY} and the
143.2292 +     *         {@code BigDecimal}  operation would require rounding.
143.2293 +     * @see    #plus(MathContext)
143.2294 +     * @since  1.5
143.2295 +     */
143.2296 +    public BigDecimal round(MathContext mc) {
143.2297 +        return plus(mc);
143.2298 +    }
143.2299 +
143.2300 +    /**
143.2301 +     * Returns a {@code BigDecimal} whose scale is the specified
143.2302 +     * value, and whose unscaled value is determined by multiplying or
143.2303 +     * dividing this {@code BigDecimal}'s unscaled value by the
143.2304 +     * appropriate power of ten to maintain its overall value.  If the
143.2305 +     * scale is reduced by the operation, the unscaled value must be
143.2306 +     * divided (rather than multiplied), and the value may be changed;
143.2307 +     * in this case, the specified rounding mode is applied to the
143.2308 +     * division.
143.2309 +     *
143.2310 +     * <p>Note that since BigDecimal objects are immutable, calls of
143.2311 +     * this method do <i>not</i> result in the original object being
143.2312 +     * modified, contrary to the usual convention of having methods
143.2313 +     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
143.2314 +     * Instead, {@code setScale} returns an object with the proper
143.2315 +     * scale; the returned object may or may not be newly allocated.
143.2316 +     *
143.2317 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
143.2318 +     * @param  roundingMode The rounding mode to apply.
143.2319 +     * @return a {@code BigDecimal} whose scale is the specified value,
143.2320 +     *         and whose unscaled value is determined by multiplying or
143.2321 +     *         dividing this {@code BigDecimal}'s unscaled value by the
143.2322 +     *         appropriate power of ten to maintain its overall value.
143.2323 +     * @throws ArithmeticException if {@code roundingMode==UNNECESSARY}
143.2324 +     *         and the specified scaling operation would require
143.2325 +     *         rounding.
143.2326 +     * @see    RoundingMode
143.2327 +     * @since  1.5
143.2328 +     */
143.2329 +    public BigDecimal setScale(int newScale, RoundingMode roundingMode) {
143.2330 +        return setScale(newScale, roundingMode.oldMode);
143.2331 +    }
143.2332 +
143.2333 +    /**
143.2334 +     * Returns a {@code BigDecimal} whose scale is the specified
143.2335 +     * value, and whose unscaled value is determined by multiplying or
143.2336 +     * dividing this {@code BigDecimal}'s unscaled value by the
143.2337 +     * appropriate power of ten to maintain its overall value.  If the
143.2338 +     * scale is reduced by the operation, the unscaled value must be
143.2339 +     * divided (rather than multiplied), and the value may be changed;
143.2340 +     * in this case, the specified rounding mode is applied to the
143.2341 +     * division.
143.2342 +     *
143.2343 +     * <p>Note that since BigDecimal objects are immutable, calls of
143.2344 +     * this method do <i>not</i> result in the original object being
143.2345 +     * modified, contrary to the usual convention of having methods
143.2346 +     * named <tt>set<i>X</i></tt> mutate field <i>{@code X}</i>.
143.2347 +     * Instead, {@code setScale} returns an object with the proper
143.2348 +     * scale; the returned object may or may not be newly allocated.
143.2349 +     *
143.2350 +     * <p>The new {@link #setScale(int, RoundingMode)} method should
143.2351 +     * be used in preference to this legacy method.
143.2352 +     *
143.2353 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
143.2354 +     * @param  roundingMode The rounding mode to apply.
143.2355 +     * @return a {@code BigDecimal} whose scale is the specified value,
143.2356 +     *         and whose unscaled value is determined by multiplying or
143.2357 +     *         dividing this {@code BigDecimal}'s unscaled value by the
143.2358 +     *         appropriate power of ten to maintain its overall value.
143.2359 +     * @throws ArithmeticException if {@code roundingMode==ROUND_UNNECESSARY}
143.2360 +     *         and the specified scaling operation would require
143.2361 +     *         rounding.
143.2362 +     * @throws IllegalArgumentException if {@code roundingMode} does not
143.2363 +     *         represent a valid rounding mode.
143.2364 +     * @see    #ROUND_UP
143.2365 +     * @see    #ROUND_DOWN
143.2366 +     * @see    #ROUND_CEILING
143.2367 +     * @see    #ROUND_FLOOR
143.2368 +     * @see    #ROUND_HALF_UP
143.2369 +     * @see    #ROUND_HALF_DOWN
143.2370 +     * @see    #ROUND_HALF_EVEN
143.2371 +     * @see    #ROUND_UNNECESSARY
143.2372 +     */
143.2373 +    public BigDecimal setScale(int newScale, int roundingMode) {
143.2374 +        if (roundingMode < ROUND_UP || roundingMode > ROUND_UNNECESSARY)
143.2375 +            throw new IllegalArgumentException("Invalid rounding mode");
143.2376 +
143.2377 +        int oldScale = this.scale;
143.2378 +        if (newScale == oldScale)        // easy case
143.2379 +            return this;
143.2380 +        if (this.signum() == 0)            // zero can have any scale
143.2381 +            return BigDecimal.valueOf(0, newScale);
143.2382 +
143.2383 +        long rs = this.intCompact;
143.2384 +        if (newScale > oldScale) {
143.2385 +            int raise = checkScale((long)newScale - oldScale);
143.2386 +            BigInteger rb = null;
143.2387 +            if (rs == INFLATED ||
143.2388 +                (rs = longMultiplyPowerTen(rs, raise)) == INFLATED)
143.2389 +                rb = bigMultiplyPowerTen(raise);
143.2390 +            return new BigDecimal(rb, rs, newScale,
143.2391 +                                  (precision > 0) ? precision + raise : 0);
143.2392 +        } else {
143.2393 +            // newScale < oldScale -- drop some digits
143.2394 +            // Can't predict the precision due to the effect of rounding.
143.2395 +            int drop = checkScale((long)oldScale - newScale);
143.2396 +            if (drop < LONG_TEN_POWERS_TABLE.length)
143.2397 +                return divideAndRound(rs, this.intVal,
143.2398 +                                      LONG_TEN_POWERS_TABLE[drop], null,
143.2399 +                                      newScale, roundingMode, newScale);
143.2400 +            else
143.2401 +                return divideAndRound(rs, this.intVal,
143.2402 +                                      INFLATED, bigTenToThe(drop),
143.2403 +                                      newScale, roundingMode, newScale);
143.2404 +        }
143.2405 +    }
143.2406 +
143.2407 +    /**
143.2408 +     * Returns a {@code BigDecimal} whose scale is the specified
143.2409 +     * value, and whose value is numerically equal to this
143.2410 +     * {@code BigDecimal}'s.  Throws an {@code ArithmeticException}
143.2411 +     * if this is not possible.
143.2412 +     *
143.2413 +     * <p>This call is typically used to increase the scale, in which
143.2414 +     * case it is guaranteed that there exists a {@code BigDecimal}
143.2415 +     * of the specified scale and the correct value.  The call can
143.2416 +     * also be used to reduce the scale if the caller knows that the
143.2417 +     * {@code BigDecimal} has sufficiently many zeros at the end of
143.2418 +     * its fractional part (i.e., factors of ten in its integer value)
143.2419 +     * to allow for the rescaling without changing its value.
143.2420 +     *
143.2421 +     * <p>This method returns the same result as the two-argument
143.2422 +     * versions of {@code setScale}, but saves the caller the trouble
143.2423 +     * of specifying a rounding mode in cases where it is irrelevant.
143.2424 +     *
143.2425 +     * <p>Note that since {@code BigDecimal} objects are immutable,
143.2426 +     * calls of this method do <i>not</i> result in the original
143.2427 +     * object being modified, contrary to the usual convention of
143.2428 +     * having methods named <tt>set<i>X</i></tt> mutate field
143.2429 +     * <i>{@code X}</i>.  Instead, {@code setScale} returns an
143.2430 +     * object with the proper scale; the returned object may or may
143.2431 +     * not be newly allocated.
143.2432 +     *
143.2433 +     * @param  newScale scale of the {@code BigDecimal} value to be returned.
143.2434 +     * @return a {@code BigDecimal} whose scale is the specified value, and
143.2435 +     *         whose unscaled value is determined by multiplying or dividing
143.2436 +     *         this {@code BigDecimal}'s unscaled value by the appropriate
143.2437 +     *         power of ten to maintain its overall value.
143.2438 +     * @throws ArithmeticException if the specified scaling operation would
143.2439 +     *         require rounding.
143.2440 +     * @see    #setScale(int, int)
143.2441 +     * @see    #setScale(int, RoundingMode)
143.2442 +     */
143.2443 +    public BigDecimal setScale(int newScale) {
143.2444 +        return setScale(newScale, ROUND_UNNECESSARY);
143.2445 +    }
143.2446 +
143.2447 +    // Decimal Point Motion Operations
143.2448 +
143.2449 +    /**
143.2450 +     * Returns a {@code BigDecimal} which is equivalent to this one
143.2451 +     * with the decimal point moved {@code n} places to the left.  If
143.2452 +     * {@code n} is non-negative, the call merely adds {@code n} to
143.2453 +     * the scale.  If {@code n} is negative, the call is equivalent
143.2454 +     * to {@code movePointRight(-n)}.  The {@code BigDecimal}
143.2455 +     * returned by this call has value <tt>(this &times;
143.2456 +     * 10<sup>-n</sup>)</tt> and scale {@code max(this.scale()+n,
143.2457 +     * 0)}.
143.2458 +     *
143.2459 +     * @param  n number of places to move the decimal point to the left.
143.2460 +     * @return a {@code BigDecimal} which is equivalent to this one with the
143.2461 +     *         decimal point moved {@code n} places to the left.
143.2462 +     * @throws ArithmeticException if scale overflows.
143.2463 +     */
143.2464 +    public BigDecimal movePointLeft(int n) {
143.2465 +        // Cannot use movePointRight(-n) in case of n==Integer.MIN_VALUE
143.2466 +        int newScale = checkScale((long)scale + n);
143.2467 +        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
143.2468 +        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
143.2469 +    }
143.2470 +
143.2471 +    /**
143.2472 +     * Returns a {@code BigDecimal} which is equivalent to this one
143.2473 +     * with the decimal point moved {@code n} places to the right.
143.2474 +     * If {@code n} is non-negative, the call merely subtracts
143.2475 +     * {@code n} from the scale.  If {@code n} is negative, the call
143.2476 +     * is equivalent to {@code movePointLeft(-n)}.  The
143.2477 +     * {@code BigDecimal} returned by this call has value <tt>(this
143.2478 +     * &times; 10<sup>n</sup>)</tt> and scale {@code max(this.scale()-n,
143.2479 +     * 0)}.
143.2480 +     *
143.2481 +     * @param  n number of places to move the decimal point to the right.
143.2482 +     * @return a {@code BigDecimal} which is equivalent to this one
143.2483 +     *         with the decimal point moved {@code n} places to the right.
143.2484 +     * @throws ArithmeticException if scale overflows.
143.2485 +     */
143.2486 +    public BigDecimal movePointRight(int n) {
143.2487 +        // Cannot use movePointLeft(-n) in case of n==Integer.MIN_VALUE
143.2488 +        int newScale = checkScale((long)scale - n);
143.2489 +        BigDecimal num = new BigDecimal(intVal, intCompact, newScale, 0);
143.2490 +        return num.scale < 0 ? num.setScale(0, ROUND_UNNECESSARY) : num;
143.2491 +    }
143.2492 +
143.2493 +    /**
143.2494 +     * Returns a BigDecimal whose numerical value is equal to
143.2495 +     * ({@code this} * 10<sup>n</sup>).  The scale of
143.2496 +     * the result is {@code (this.scale() - n)}.
143.2497 +     *
143.2498 +     * @throws ArithmeticException if the scale would be
143.2499 +     *         outside the range of a 32-bit integer.
143.2500 +     *
143.2501 +     * @since 1.5
143.2502 +     */
143.2503 +    public BigDecimal scaleByPowerOfTen(int n) {
143.2504 +        return new BigDecimal(intVal, intCompact,
143.2505 +                              checkScale((long)scale - n), precision);
143.2506 +    }
143.2507 +
143.2508 +    /**
143.2509 +     * Returns a {@code BigDecimal} which is numerically equal to
143.2510 +     * this one but with any trailing zeros removed from the
143.2511 +     * representation.  For example, stripping the trailing zeros from
143.2512 +     * the {@code BigDecimal} value {@code 600.0}, which has
143.2513 +     * [{@code BigInteger}, {@code scale}] components equals to
143.2514 +     * [6000, 1], yields {@code 6E2} with [{@code BigInteger},
143.2515 +     * {@code scale}] components equals to [6, -2]
143.2516 +     *
143.2517 +     * @return a numerically equal {@code BigDecimal} with any
143.2518 +     * trailing zeros removed.
143.2519 +     * @since 1.5
143.2520 +     */
143.2521 +    public BigDecimal stripTrailingZeros() {
143.2522 +        this.inflate();
143.2523 +        BigDecimal result = new BigDecimal(intVal, scale);
143.2524 +        result.stripZerosToMatchScale(Long.MIN_VALUE);
143.2525 +        return result;
143.2526 +    }
143.2527 +
143.2528 +    // Comparison Operations
143.2529 +
143.2530 +    /**
143.2531 +     * Compares this {@code BigDecimal} with the specified
143.2532 +     * {@code BigDecimal}.  Two {@code BigDecimal} objects that are
143.2533 +     * equal in value but have a different scale (like 2.0 and 2.00)
143.2534 +     * are considered equal by this method.  This method is provided
143.2535 +     * in preference to individual methods for each of the six boolean
143.2536 +     * comparison operators ({@literal <}, ==,
143.2537 +     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The
143.2538 +     * suggested idiom for performing these comparisons is:
143.2539 +     * {@code (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
143.2540 +     * &lt;<i>op</i>&gt; is one of the six comparison operators.
143.2541 +     *
143.2542 +     * @param  val {@code BigDecimal} to which this {@code BigDecimal} is
143.2543 +     *         to be compared.
143.2544 +     * @return -1, 0, or 1 as this {@code BigDecimal} is numerically
143.2545 +     *          less than, equal to, or greater than {@code val}.
143.2546 +     */
143.2547 +    public int compareTo(BigDecimal val) {
143.2548 +        // Quick path for equal scale and non-inflated case.
143.2549 +        if (scale == val.scale) {
143.2550 +            long xs = intCompact;
143.2551 +            long ys = val.intCompact;
143.2552 +            if (xs != INFLATED && ys != INFLATED)
143.2553 +                return xs != ys ? ((xs > ys) ? 1 : -1) : 0;
143.2554 +        }
143.2555 +        int xsign = this.signum();
143.2556 +        int ysign = val.signum();
143.2557 +        if (xsign != ysign)
143.2558 +            return (xsign > ysign) ? 1 : -1;
143.2559 +        if (xsign == 0)
143.2560 +            return 0;
143.2561 +        int cmp = compareMagnitude(val);
143.2562 +        return (xsign > 0) ? cmp : -cmp;
143.2563 +    }
143.2564 +
143.2565 +    /**
143.2566 +     * Version of compareTo that ignores sign.
143.2567 +     */
143.2568 +    private int compareMagnitude(BigDecimal val) {
143.2569 +        // Match scales, avoid unnecessary inflation
143.2570 +        long ys = val.intCompact;
143.2571 +        long xs = this.intCompact;
143.2572 +        if (xs == 0)
143.2573 +            return (ys == 0) ? 0 : -1;
143.2574 +        if (ys == 0)
143.2575 +            return 1;
143.2576 +
143.2577 +        int sdiff = this.scale - val.scale;
143.2578 +        if (sdiff != 0) {
143.2579 +            // Avoid matching scales if the (adjusted) exponents differ
143.2580 +            int xae = this.precision() - this.scale;   // [-1]
143.2581 +            int yae = val.precision() - val.scale;     // [-1]
143.2582 +            if (xae < yae)
143.2583 +                return -1;
143.2584 +            if (xae > yae)
143.2585 +                return 1;
143.2586 +            BigInteger rb = null;
143.2587 +            if (sdiff < 0) {
143.2588 +                if ( (xs == INFLATED ||
143.2589 +                      (xs = longMultiplyPowerTen(xs, -sdiff)) == INFLATED) &&
143.2590 +                     ys == INFLATED) {
143.2591 +                    rb = bigMultiplyPowerTen(-sdiff);
143.2592 +                    return rb.compareMagnitude(val.intVal);
143.2593 +                }
143.2594 +            } else { // sdiff > 0
143.2595 +                if ( (ys == INFLATED ||
143.2596 +                      (ys = longMultiplyPowerTen(ys, sdiff)) == INFLATED) &&
143.2597 +                     xs == INFLATED) {
143.2598 +                    rb = val.bigMultiplyPowerTen(sdiff);
143.2599 +                    return this.intVal.compareMagnitude(rb);
143.2600 +                }
143.2601 +            }
143.2602 +        }
143.2603 +        if (xs != INFLATED)
143.2604 +            return (ys != INFLATED) ? longCompareMagnitude(xs, ys) : -1;
143.2605 +        else if (ys != INFLATED)
143.2606 +            return 1;
143.2607 +        else
143.2608 +            return this.intVal.compareMagnitude(val.intVal);
143.2609 +    }
143.2610 +
143.2611 +    /**
143.2612 +     * Compares this {@code BigDecimal} with the specified
143.2613 +     * {@code Object} for equality.  Unlike {@link
143.2614 +     * #compareTo(BigDecimal) compareTo}, this method considers two
143.2615 +     * {@code BigDecimal} objects equal only if they are equal in
143.2616 +     * value and scale (thus 2.0 is not equal to 2.00 when compared by
143.2617 +     * this method).
143.2618 +     *
143.2619 +     * @param  x {@code Object} to which this {@code BigDecimal} is
143.2620 +     *         to be compared.
143.2621 +     * @return {@code true} if and only if the specified {@code Object} is a
143.2622 +     *         {@code BigDecimal} whose value and scale are equal to this
143.2623 +     *         {@code BigDecimal}'s.
143.2624 +     * @see    #compareTo(java.math.BigDecimal)
143.2625 +     * @see    #hashCode
143.2626 +     */
143.2627 +    @Override
143.2628 +    public boolean equals(Object x) {
143.2629 +        if (!(x instanceof BigDecimal))
143.2630 +            return false;
143.2631 +        BigDecimal xDec = (BigDecimal) x;
143.2632 +        if (x == this)
143.2633 +            return true;
143.2634 +        if (scale != xDec.scale)
143.2635 +            return false;
143.2636 +        long s = this.intCompact;
143.2637 +        long xs = xDec.intCompact;
143.2638 +        if (s != INFLATED) {
143.2639 +            if (xs == INFLATED)
143.2640 +                xs = compactValFor(xDec.intVal);
143.2641 +            return xs == s;
143.2642 +        } else if (xs != INFLATED)
143.2643 +            return xs == compactValFor(this.intVal);
143.2644 +
143.2645 +        return this.inflate().equals(xDec.inflate());
143.2646 +    }
143.2647 +
143.2648 +    /**
143.2649 +     * Returns the minimum of this {@code BigDecimal} and
143.2650 +     * {@code val}.
143.2651 +     *
143.2652 +     * @param  val value with which the minimum is to be computed.
143.2653 +     * @return the {@code BigDecimal} whose value is the lesser of this
143.2654 +     *         {@code BigDecimal} and {@code val}.  If they are equal,
143.2655 +     *         as defined by the {@link #compareTo(BigDecimal) compareTo}
143.2656 +     *         method, {@code this} is returned.
143.2657 +     * @see    #compareTo(java.math.BigDecimal)
143.2658 +     */
143.2659 +    public BigDecimal min(BigDecimal val) {
143.2660 +        return (compareTo(val) <= 0 ? this : val);
143.2661 +    }
143.2662 +
143.2663 +    /**
143.2664 +     * Returns the maximum of this {@code BigDecimal} and {@code val}.
143.2665 +     *
143.2666 +     * @param  val value with which the maximum is to be computed.
143.2667 +     * @return the {@code BigDecimal} whose value is the greater of this
143.2668 +     *         {@code BigDecimal} and {@code val}.  If they are equal,
143.2669 +     *         as defined by the {@link #compareTo(BigDecimal) compareTo}
143.2670 +     *         method, {@code this} is returned.
143.2671 +     * @see    #compareTo(java.math.BigDecimal)
143.2672 +     */
143.2673 +    public BigDecimal max(BigDecimal val) {
143.2674 +        return (compareTo(val) >= 0 ? this : val);
143.2675 +    }
143.2676 +
143.2677 +    // Hash Function
143.2678 +
143.2679 +    /**
143.2680 +     * Returns the hash code for this {@code BigDecimal}.  Note that
143.2681 +     * two {@code BigDecimal} objects that are numerically equal but
143.2682 +     * differ in scale (like 2.0 and 2.00) will generally <i>not</i>
143.2683 +     * have the same hash code.
143.2684 +     *
143.2685 +     * @return hash code for this {@code BigDecimal}.
143.2686 +     * @see #equals(Object)
143.2687 +     */
143.2688 +    @Override
143.2689 +    public int hashCode() {
143.2690 +        if (intCompact != INFLATED) {
143.2691 +            long val2 = (intCompact < 0)? -intCompact : intCompact;
143.2692 +            int temp = (int)( ((int)(val2 >>> 32)) * 31  +
143.2693 +                              (val2 & LONG_MASK));
143.2694 +            return 31*((intCompact < 0) ?-temp:temp) + scale;
143.2695 +        } else
143.2696 +            return 31*intVal.hashCode() + scale;
143.2697 +    }
143.2698 +
143.2699 +    // Format Converters
143.2700 +
143.2701 +    /**
143.2702 +     * Returns the string representation of this {@code BigDecimal},
143.2703 +     * using scientific notation if an exponent is needed.
143.2704 +     *
143.2705 +     * <p>A standard canonical string form of the {@code BigDecimal}
143.2706 +     * is created as though by the following steps: first, the
143.2707 +     * absolute value of the unscaled value of the {@code BigDecimal}
143.2708 +     * is converted to a string in base ten using the characters
143.2709 +     * {@code '0'} through {@code '9'} with no leading zeros (except
143.2710 +     * if its value is zero, in which case a single {@code '0'}
143.2711 +     * character is used).
143.2712 +     *
143.2713 +     * <p>Next, an <i>adjusted exponent</i> is calculated; this is the
143.2714 +     * negated scale, plus the number of characters in the converted
143.2715 +     * unscaled value, less one.  That is,
143.2716 +     * {@code -scale+(ulength-1)}, where {@code ulength} is the
143.2717 +     * length of the absolute value of the unscaled value in decimal
143.2718 +     * digits (its <i>precision</i>).
143.2719 +     *
143.2720 +     * <p>If the scale is greater than or equal to zero and the
143.2721 +     * adjusted exponent is greater than or equal to {@code -6}, the
143.2722 +     * number will be converted to a character form without using
143.2723 +     * exponential notation.  In this case, if the scale is zero then
143.2724 +     * no decimal point is added and if the scale is positive a
143.2725 +     * decimal point will be inserted with the scale specifying the
143.2726 +     * number of characters to the right of the decimal point.
143.2727 +     * {@code '0'} characters are added to the left of the converted
143.2728 +     * unscaled value as necessary.  If no character precedes the
143.2729 +     * decimal point after this insertion then a conventional
143.2730 +     * {@code '0'} character is prefixed.
143.2731 +     *
143.2732 +     * <p>Otherwise (that is, if the scale is negative, or the
143.2733 +     * adjusted exponent is less than {@code -6}), the number will be
143.2734 +     * converted to a character form using exponential notation.  In
143.2735 +     * this case, if the converted {@code BigInteger} has more than
143.2736 +     * one digit a decimal point is inserted after the first digit.
143.2737 +     * An exponent in character form is then suffixed to the converted
143.2738 +     * unscaled value (perhaps with inserted decimal point); this
143.2739 +     * comprises the letter {@code 'E'} followed immediately by the
143.2740 +     * adjusted exponent converted to a character form.  The latter is
143.2741 +     * in base ten, using the characters {@code '0'} through
143.2742 +     * {@code '9'} with no leading zeros, and is always prefixed by a
143.2743 +     * sign character {@code '-'} (<tt>'&#92;u002D'</tt>) if the
143.2744 +     * adjusted exponent is negative, {@code '+'}
143.2745 +     * (<tt>'&#92;u002B'</tt>) otherwise).
143.2746 +     *
143.2747 +     * <p>Finally, the entire string is prefixed by a minus sign
143.2748 +     * character {@code '-'} (<tt>'&#92;u002D'</tt>) if the unscaled
143.2749 +     * value is less than zero.  No sign character is prefixed if the
143.2750 +     * unscaled value is zero or positive.
143.2751 +     *
143.2752 +     * <p><b>Examples:</b>
143.2753 +     * <p>For each representation [<i>unscaled value</i>, <i>scale</i>]
143.2754 +     * on the left, the resulting string is shown on the right.
143.2755 +     * <pre>
143.2756 +     * [123,0]      "123"
143.2757 +     * [-123,0]     "-123"
143.2758 +     * [123,-1]     "1.23E+3"
143.2759 +     * [123,-3]     "1.23E+5"
143.2760 +     * [123,1]      "12.3"
143.2761 +     * [123,5]      "0.00123"
143.2762 +     * [123,10]     "1.23E-8"
143.2763 +     * [-123,12]    "-1.23E-10"
143.2764 +     * </pre>
143.2765 +     *
143.2766 +     * <b>Notes:</b>
143.2767 +     * <ol>
143.2768 +     *
143.2769 +     * <li>There is a one-to-one mapping between the distinguishable
143.2770 +     * {@code BigDecimal} values and the result of this conversion.
143.2771 +     * That is, every distinguishable {@code BigDecimal} value
143.2772 +     * (unscaled value and scale) has a unique string representation
143.2773 +     * as a result of using {@code toString}.  If that string
143.2774 +     * representation is converted back to a {@code BigDecimal} using
143.2775 +     * the {@link #BigDecimal(String)} constructor, then the original
143.2776 +     * value will be recovered.
143.2777 +     *
143.2778 +     * <li>The string produced for a given number is always the same;
143.2779 +     * it is not affected by locale.  This means that it can be used
143.2780 +     * as a canonical string representation for exchanging decimal
143.2781 +     * data, or as a key for a Hashtable, etc.  Locale-sensitive
143.2782 +     * number formatting and parsing is handled by the {@link
143.2783 +     * java.text.NumberFormat} class and its subclasses.
143.2784 +     *
143.2785 +     * <li>The {@link #toEngineeringString} method may be used for
143.2786 +     * presenting numbers with exponents in engineering notation, and the
143.2787 +     * {@link #setScale(int,RoundingMode) setScale} method may be used for
143.2788 +     * rounding a {@code BigDecimal} so it has a known number of digits after
143.2789 +     * the decimal point.
143.2790 +     *
143.2791 +     * <li>The digit-to-character mapping provided by
143.2792 +     * {@code Character.forDigit} is used.
143.2793 +     *
143.2794 +     * </ol>
143.2795 +     *
143.2796 +     * @return string representation of this {@code BigDecimal}.
143.2797 +     * @see    Character#forDigit
143.2798 +     * @see    #BigDecimal(java.lang.String)
143.2799 +     */
143.2800 +    @Override
143.2801 +    public String toString() {
143.2802 +        String sc = stringCache;
143.2803 +        if (sc == null)
143.2804 +            stringCache = sc = layoutChars(true);
143.2805 +        return sc;
143.2806 +    }
143.2807 +
143.2808 +    /**
143.2809 +     * Returns a string representation of this {@code BigDecimal},
143.2810 +     * using engineering notation if an exponent is needed.
143.2811 +     *
143.2812 +     * <p>Returns a string that represents the {@code BigDecimal} as
143.2813 +     * described in the {@link #toString()} method, except that if
143.2814 +     * exponential notation is used, the power of ten is adjusted to
143.2815 +     * be a multiple of three (engineering notation) such that the
143.2816 +     * integer part of nonzero values will be in the range 1 through
143.2817 +     * 999.  If exponential notation is used for zero values, a
143.2818 +     * decimal point and one or two fractional zero digits are used so
143.2819 +     * that the scale of the zero value is preserved.  Note that
143.2820 +     * unlike the output of {@link #toString()}, the output of this
143.2821 +     * method is <em>not</em> guaranteed to recover the same [integer,
143.2822 +     * scale] pair of this {@code BigDecimal} if the output string is
143.2823 +     * converting back to a {@code BigDecimal} using the {@linkplain
143.2824 +     * #BigDecimal(String) string constructor}.  The result of this method meets
143.2825 +     * the weaker constraint of always producing a numerically equal
143.2826 +     * result from applying the string constructor to the method's output.
143.2827 +     *
143.2828 +     * @return string representation of this {@code BigDecimal}, using
143.2829 +     *         engineering notation if an exponent is needed.
143.2830 +     * @since  1.5
143.2831 +     */
143.2832 +    public String toEngineeringString() {
143.2833 +        return layoutChars(false);
143.2834 +    }
143.2835 +
143.2836 +    /**
143.2837 +     * Returns a string representation of this {@code BigDecimal}
143.2838 +     * without an exponent field.  For values with a positive scale,
143.2839 +     * the number of digits to the right of the decimal point is used
143.2840 +     * to indicate scale.  For values with a zero or negative scale,
143.2841 +     * the resulting string is generated as if the value were
143.2842 +     * converted to a numerically equal value with zero scale and as
143.2843 +     * if all the trailing zeros of the zero scale value were present
143.2844 +     * in the result.
143.2845 +     *
143.2846 +     * The entire string is prefixed by a minus sign character '-'
143.2847 +     * (<tt>'&#92;u002D'</tt>) if the unscaled value is less than
143.2848 +     * zero. No sign character is prefixed if the unscaled value is
143.2849 +     * zero or positive.
143.2850 +     *
143.2851 +     * Note that if the result of this method is passed to the
143.2852 +     * {@linkplain #BigDecimal(String) string constructor}, only the
143.2853 +     * numerical value of this {@code BigDecimal} will necessarily be
143.2854 +     * recovered; the representation of the new {@code BigDecimal}
143.2855 +     * may have a different scale.  In particular, if this
143.2856 +     * {@code BigDecimal} has a negative scale, the string resulting
143.2857 +     * from this method will have a scale of zero when processed by
143.2858 +     * the string constructor.
143.2859 +     *
143.2860 +     * (This method behaves analogously to the {@code toString}
143.2861 +     * method in 1.4 and earlier releases.)
143.2862 +     *
143.2863 +     * @return a string representation of this {@code BigDecimal}
143.2864 +     * without an exponent field.
143.2865 +     * @since 1.5
143.2866 +     * @see #toString()
143.2867 +     * @see #toEngineeringString()
143.2868 +     */
143.2869 +    public String toPlainString() {
143.2870 +        BigDecimal bd = this;
143.2871 +        if (bd.scale < 0)
143.2872 +            bd = bd.setScale(0);
143.2873 +        bd.inflate();
143.2874 +        if (bd.scale == 0)      // No decimal point
143.2875 +            return bd.intVal.toString();
143.2876 +        return bd.getValueString(bd.signum(), bd.intVal.abs().toString(), bd.scale);
143.2877 +    }
143.2878 +
143.2879 +    /* Returns a digit.digit string */
143.2880 +    private String getValueString(int signum, String intString, int scale) {
143.2881 +        /* Insert decimal point */
143.2882 +        StringBuilder buf;
143.2883 +        int insertionPoint = intString.length() - scale;
143.2884 +        if (insertionPoint == 0) {  /* Point goes right before intVal */
143.2885 +            return (signum<0 ? "-0." : "0.") + intString;
143.2886 +        } else if (insertionPoint > 0) { /* Point goes inside intVal */
143.2887 +            buf = new StringBuilder(intString);
143.2888 +            buf.insert(insertionPoint, '.');
143.2889 +            if (signum < 0)
143.2890 +                buf.insert(0, '-');
143.2891 +        } else { /* We must insert zeros between point and intVal */
143.2892 +            buf = new StringBuilder(3-insertionPoint + intString.length());
143.2893 +            buf.append(signum<0 ? "-0." : "0.");
143.2894 +            for (int i=0; i<-insertionPoint; i++)
143.2895 +                buf.append('0');
143.2896 +            buf.append(intString);
143.2897 +        }
143.2898 +        return buf.toString();
143.2899 +    }
143.2900 +
143.2901 +    /**
143.2902 +     * Converts this {@code BigDecimal} to a {@code BigInteger}.
143.2903 +     * This conversion is analogous to the
143.2904 +     * <i>narrowing primitive conversion</i> from {@code double} to
143.2905 +     * {@code long} as defined in section 5.1.3 of
143.2906 +     * <cite>The Java&trade; Language Specification</cite>:
143.2907 +     * any fractional part of this
143.2908 +     * {@code BigDecimal} will be discarded.  Note that this
143.2909 +     * conversion can lose information about the precision of the
143.2910 +     * {@code BigDecimal} value.
143.2911 +     * <p>
143.2912 +     * To have an exception thrown if the conversion is inexact (in
143.2913 +     * other words if a nonzero fractional part is discarded), use the
143.2914 +     * {@link #toBigIntegerExact()} method.
143.2915 +     *
143.2916 +     * @return this {@code BigDecimal} converted to a {@code BigInteger}.
143.2917 +     */
143.2918 +    public BigInteger toBigInteger() {
143.2919 +        // force to an integer, quietly
143.2920 +        return this.setScale(0, ROUND_DOWN).inflate();
143.2921 +    }
143.2922 +
143.2923 +    /**
143.2924 +     * Converts this {@code BigDecimal} to a {@code BigInteger},
143.2925 +     * checking for lost information.  An exception is thrown if this
143.2926 +     * {@code BigDecimal} has a nonzero fractional part.
143.2927 +     *
143.2928 +     * @return this {@code BigDecimal} converted to a {@code BigInteger}.
143.2929 +     * @throws ArithmeticException if {@code this} has a nonzero
143.2930 +     *         fractional part.
143.2931 +     * @since  1.5
143.2932 +     */
143.2933 +    public BigInteger toBigIntegerExact() {
143.2934 +        // round to an integer, with Exception if decimal part non-0
143.2935 +        return this.setScale(0, ROUND_UNNECESSARY).inflate();
143.2936 +    }
143.2937 +
143.2938 +    /**
143.2939 +     * Converts this {@code BigDecimal} to a {@code long}.
143.2940 +     * This conversion is analogous to the
143.2941 +     * <i>narrowing primitive conversion</i> from {@code double} to
143.2942 +     * {@code short} as defined in section 5.1.3 of
143.2943 +     * <cite>The Java&trade; Language Specification</cite>:
143.2944 +     * any fractional part of this
143.2945 +     * {@code BigDecimal} will be discarded, and if the resulting
143.2946 +     * "{@code BigInteger}" is too big to fit in a
143.2947 +     * {@code long}, only the low-order 64 bits are returned.
143.2948 +     * Note that this conversion can lose information about the
143.2949 +     * overall magnitude and precision of this {@code BigDecimal} value as well
143.2950 +     * as return a result with the opposite sign.
143.2951 +     *
143.2952 +     * @return this {@code BigDecimal} converted to a {@code long}.
143.2953 +     */
143.2954 +    public long longValue(){
143.2955 +        return (intCompact != INFLATED && scale == 0) ?
143.2956 +            intCompact:
143.2957 +            toBigInteger().longValue();
143.2958 +    }
143.2959 +
143.2960 +    /**
143.2961 +     * Converts this {@code BigDecimal} to a {@code long}, checking
143.2962 +     * for lost information.  If this {@code BigDecimal} has a
143.2963 +     * nonzero fractional part or is out of the possible range for a
143.2964 +     * {@code long} result then an {@code ArithmeticException} is
143.2965 +     * thrown.
143.2966 +     *
143.2967 +     * @return this {@code BigDecimal} converted to a {@code long}.
143.2968 +     * @throws ArithmeticException if {@code this} has a nonzero
143.2969 +     *         fractional part, or will not fit in a {@code long}.
143.2970 +     * @since  1.5
143.2971 +     */
143.2972 +    public long longValueExact() {
143.2973 +        if (intCompact != INFLATED && scale == 0)
143.2974 +            return intCompact;
143.2975 +        // If more than 19 digits in integer part it cannot possibly fit
143.2976 +        if ((precision() - scale) > 19) // [OK for negative scale too]
143.2977 +            throw new java.lang.ArithmeticException("Overflow");
143.2978 +        // Fastpath zero and < 1.0 numbers (the latter can be very slow
143.2979 +        // to round if very small)
143.2980 +        if (this.signum() == 0)
143.2981 +            return 0;
143.2982 +        if ((this.precision() - this.scale) <= 0)
143.2983 +            throw new ArithmeticException("Rounding necessary");
143.2984 +        // round to an integer, with Exception if decimal part non-0
143.2985 +        BigDecimal num = this.setScale(0, ROUND_UNNECESSARY);
143.2986 +        if (num.precision() >= 19) // need to check carefully
143.2987 +            LongOverflow.check(num);
143.2988 +        return num.inflate().longValue();
143.2989 +    }
143.2990 +
143.2991 +    private static class LongOverflow {
143.2992 +        /** BigInteger equal to Long.MIN_VALUE. */
143.2993 +        private static final BigInteger LONGMIN = BigInteger.valueOf(Long.MIN_VALUE);
143.2994 +
143.2995 +        /** BigInteger equal to Long.MAX_VALUE. */
143.2996 +        private static final BigInteger LONGMAX = BigInteger.valueOf(Long.MAX_VALUE);
143.2997 +
143.2998 +        public static void check(BigDecimal num) {
143.2999 +            num.inflate();
143.3000 +            if ((num.intVal.compareTo(LONGMIN) < 0) ||
143.3001 +                (num.intVal.compareTo(LONGMAX) > 0))
143.3002 +                throw new java.lang.ArithmeticException("Overflow");
143.3003 +        }
143.3004 +    }
143.3005 +
143.3006 +    /**
143.3007 +     * Converts this {@code BigDecimal} to an {@code int}.
143.3008 +     * This conversion is analogous to the
143.3009 +     * <i>narrowing primitive conversion</i> from {@code double} to
143.3010 +     * {@code short} as defined in section 5.1.3 of
143.3011 +     * <cite>The Java&trade; Language Specification</cite>:
143.3012 +     * any fractional part of this
143.3013 +     * {@code BigDecimal} will be discarded, and if the resulting
143.3014 +     * "{@code BigInteger}" is too big to fit in an
143.3015 +     * {@code int}, only the low-order 32 bits are returned.
143.3016 +     * Note that this conversion can lose information about the
143.3017 +     * overall magnitude and precision of this {@code BigDecimal}
143.3018 +     * value as well as return a result with the opposite sign.
143.3019 +     *
143.3020 +     * @return this {@code BigDecimal} converted to an {@code int}.
143.3021 +     */
143.3022 +    public int intValue() {
143.3023 +        return  (intCompact != INFLATED && scale == 0) ?
143.3024 +            (int)intCompact :
143.3025 +            toBigInteger().intValue();
143.3026 +    }
143.3027 +
143.3028 +    /**
143.3029 +     * Converts this {@code BigDecimal} to an {@code int}, checking
143.3030 +     * for lost information.  If this {@code BigDecimal} has a
143.3031 +     * nonzero fractional part or is out of the possible range for an
143.3032 +     * {@code int} result then an {@code ArithmeticException} is
143.3033 +     * thrown.
143.3034 +     *
143.3035 +     * @return this {@code BigDecimal} converted to an {@code int}.
143.3036 +     * @throws ArithmeticException if {@code this} has a nonzero
143.3037 +     *         fractional part, or will not fit in an {@code int}.
143.3038 +     * @since  1.5
143.3039 +     */
143.3040 +    public int intValueExact() {
143.3041 +       long num;
143.3042 +       num = this.longValueExact();     // will check decimal part
143.3043 +       if ((int)num != num)
143.3044 +           throw new java.lang.ArithmeticException("Overflow");
143.3045 +       return (int)num;
143.3046 +    }
143.3047 +
143.3048 +    /**
143.3049 +     * Converts this {@code BigDecimal} to a {@code short}, checking
143.3050 +     * for lost information.  If this {@code BigDecimal} has a
143.3051 +     * nonzero fractional part or is out of the possible range for a
143.3052 +     * {@code short} result then an {@code ArithmeticException} is
143.3053 +     * thrown.
143.3054 +     *
143.3055 +     * @return this {@code BigDecimal} converted to a {@code short}.
143.3056 +     * @throws ArithmeticException if {@code this} has a nonzero
143.3057 +     *         fractional part, or will not fit in a {@code short}.
143.3058 +     * @since  1.5
143.3059 +     */
143.3060 +    public short shortValueExact() {
143.3061 +       long num;
143.3062 +       num = this.longValueExact();     // will check decimal part
143.3063 +       if ((short)num != num)
143.3064 +           throw new java.lang.ArithmeticException("Overflow");
143.3065 +       return (short)num;
143.3066 +    }
143.3067 +
143.3068 +    /**
143.3069 +     * Converts this {@code BigDecimal} to a {@code byte}, checking
143.3070 +     * for lost information.  If this {@code BigDecimal} has a
143.3071 +     * nonzero fractional part or is out of the possible range for a
143.3072 +     * {@code byte} result then an {@code ArithmeticException} is
143.3073 +     * thrown.
143.3074 +     *
143.3075 +     * @return this {@code BigDecimal} converted to a {@code byte}.
143.3076 +     * @throws ArithmeticException if {@code this} has a nonzero
143.3077 +     *         fractional part, or will not fit in a {@code byte}.
143.3078 +     * @since  1.5
143.3079 +     */
143.3080 +    public byte byteValueExact() {
143.3081 +       long num;
143.3082 +       num = this.longValueExact();     // will check decimal part
143.3083 +       if ((byte)num != num)
143.3084 +           throw new java.lang.ArithmeticException("Overflow");
143.3085 +       return (byte)num;
143.3086 +    }
143.3087 +
143.3088 +    /**
143.3089 +     * Converts this {@code BigDecimal} to a {@code float}.
143.3090 +     * This conversion is similar to the
143.3091 +     * <i>narrowing primitive conversion</i> from {@code double} to
143.3092 +     * {@code float} as defined in section 5.1.3 of
143.3093 +     * <cite>The Java&trade; Language Specification</cite>:
143.3094 +     * if this {@code BigDecimal} has too great a
143.3095 +     * magnitude to represent as a {@code float}, it will be
143.3096 +     * converted to {@link Float#NEGATIVE_INFINITY} or {@link
143.3097 +     * Float#POSITIVE_INFINITY} as appropriate.  Note that even when
143.3098 +     * the return value is finite, this conversion can lose
143.3099 +     * information about the precision of the {@code BigDecimal}
143.3100 +     * value.
143.3101 +     *
143.3102 +     * @return this {@code BigDecimal} converted to a {@code float}.
143.3103 +     */
143.3104 +    public float floatValue(){
143.3105 +        if (scale == 0 && intCompact != INFLATED)
143.3106 +                return (float)intCompact;
143.3107 +        // Somewhat inefficient, but guaranteed to work.
143.3108 +        return Float.parseFloat(this.toString());
143.3109 +    }
143.3110 +
143.3111 +    /**
143.3112 +     * Converts this {@code BigDecimal} to a {@code double}.
143.3113 +     * This conversion is similar to the
143.3114 +     * <i>narrowing primitive conversion</i> from {@code double} to
143.3115 +     * {@code float} as defined in section 5.1.3 of
143.3116 +     * <cite>The Java&trade; Language Specification</cite>:
143.3117 +     * if this {@code BigDecimal} has too great a
143.3118 +     * magnitude represent as a {@code double}, it will be
143.3119 +     * converted to {@link Double#NEGATIVE_INFINITY} or {@link
143.3120 +     * Double#POSITIVE_INFINITY} as appropriate.  Note that even when
143.3121 +     * the return value is finite, this conversion can lose
143.3122 +     * information about the precision of the {@code BigDecimal}
143.3123 +     * value.
143.3124 +     *
143.3125 +     * @return this {@code BigDecimal} converted to a {@code double}.
143.3126 +     */
143.3127 +    public double doubleValue(){
143.3128 +        if (scale == 0 && intCompact != INFLATED)
143.3129 +            return (double)intCompact;
143.3130 +        // Somewhat inefficient, but guaranteed to work.
143.3131 +        return Double.parseDouble(this.toString());
143.3132 +    }
143.3133 +
143.3134 +    /**
143.3135 +     * Returns the size of an ulp, a unit in the last place, of this
143.3136 +     * {@code BigDecimal}.  An ulp of a nonzero {@code BigDecimal}
143.3137 +     * value is the positive distance between this value and the
143.3138 +     * {@code BigDecimal} value next larger in magnitude with the
143.3139 +     * same number of digits.  An ulp of a zero value is numerically
143.3140 +     * equal to 1 with the scale of {@code this}.  The result is
143.3141 +     * stored with the same scale as {@code this} so the result
143.3142 +     * for zero and nonzero values is equal to {@code [1,
143.3143 +     * this.scale()]}.
143.3144 +     *
143.3145 +     * @return the size of an ulp of {@code this}
143.3146 +     * @since 1.5
143.3147 +     */
143.3148 +    public BigDecimal ulp() {
143.3149 +        return BigDecimal.valueOf(1, this.scale());
143.3150 +    }
143.3151 +
143.3152 +
143.3153 +    // Private class to build a string representation for BigDecimal object.
143.3154 +    // "StringBuilderHelper" is constructed as a thread local variable so it is
143.3155 +    // thread safe. The StringBuilder field acts as a buffer to hold the temporary
143.3156 +    // representation of BigDecimal. The cmpCharArray holds all the characters for
143.3157 +    // the compact representation of BigDecimal (except for '-' sign' if it is
143.3158 +    // negative) if its intCompact field is not INFLATED. It is shared by all
143.3159 +    // calls to toString() and its variants in that particular thread.
143.3160 +    static class StringBuilderHelper {
143.3161 +        private static StringBuilderHelper INSTANCE = new StringBuilderHelper();
143.3162 +        final StringBuilder sb;    // Placeholder for BigDecimal string
143.3163 +        final char[] cmpCharArray; // character array to place the intCompact
143.3164 +
143.3165 +        StringBuilderHelper() {
143.3166 +            sb = new StringBuilder();
143.3167 +            // All non negative longs can be made to fit into 19 character array.
143.3168 +            cmpCharArray = new char[19];
143.3169 +        }
143.3170 +
143.3171 +        // Accessors.
143.3172 +        StringBuilder getStringBuilder() {
143.3173 +            sb.setLength(0);
143.3174 +            return sb;
143.3175 +        }
143.3176 +
143.3177 +        char[] getCompactCharArray() {
143.3178 +            return cmpCharArray;
143.3179 +        }
143.3180 +
143.3181 +        /**
143.3182 +         * Places characters representing the intCompact in {@code long} into
143.3183 +         * cmpCharArray and returns the offset to the array where the
143.3184 +         * representation starts.
143.3185 +         *
143.3186 +         * @param intCompact the number to put into the cmpCharArray.
143.3187 +         * @return offset to the array where the representation starts.
143.3188 +         * Note: intCompact must be greater or equal to zero.
143.3189 +         */
143.3190 +        int putIntCompact(long intCompact) {
143.3191 +            assert intCompact >= 0;
143.3192 +
143.3193 +            long q;
143.3194 +            int r;
143.3195 +            // since we start from the least significant digit, charPos points to
143.3196 +            // the last character in cmpCharArray.
143.3197 +            int charPos = cmpCharArray.length;
143.3198 +
143.3199 +            // Get 2 digits/iteration using longs until quotient fits into an int
143.3200 +            while (intCompact > Integer.MAX_VALUE) {
143.3201 +                q = intCompact / 100;
143.3202 +                r = (int)(intCompact - q * 100);
143.3203 +                intCompact = q;
143.3204 +                cmpCharArray[--charPos] = DIGIT_ONES[r];
143.3205 +                cmpCharArray[--charPos] = DIGIT_TENS[r];
143.3206 +            }
143.3207 +
143.3208 +            // Get 2 digits/iteration using ints when i2 >= 100
143.3209 +            int q2;
143.3210 +            int i2 = (int)intCompact;
143.3211 +            while (i2 >= 100) {
143.3212 +                q2 = i2 / 100;
143.3213 +                r  = i2 - q2 * 100;
143.3214 +                i2 = q2;
143.3215 +                cmpCharArray[--charPos] = DIGIT_ONES[r];
143.3216 +                cmpCharArray[--charPos] = DIGIT_TENS[r];
143.3217 +            }
143.3218 +
143.3219 +            cmpCharArray[--charPos] = DIGIT_ONES[i2];
143.3220 +            if (i2 >= 10)
143.3221 +                cmpCharArray[--charPos] = DIGIT_TENS[i2];
143.3222 +
143.3223 +            return charPos;
143.3224 +        }
143.3225 +
143.3226 +        final static char[] DIGIT_TENS = {
143.3227 +            '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
143.3228 +            '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
143.3229 +            '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
143.3230 +            '3', '3', '3', '3', '3', '3', '3', '3', '3', '3',
143.3231 +            '4', '4', '4', '4', '4', '4', '4', '4', '4', '4',
143.3232 +            '5', '5', '5', '5', '5', '5', '5', '5', '5', '5',
143.3233 +            '6', '6', '6', '6', '6', '6', '6', '6', '6', '6',
143.3234 +            '7', '7', '7', '7', '7', '7', '7', '7', '7', '7',
143.3235 +            '8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
143.3236 +            '9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
143.3237 +        };
143.3238 +
143.3239 +        final static char[] DIGIT_ONES = {
143.3240 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3241 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3242 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3243 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3244 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3245 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3246 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3247 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3248 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3249 +            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
143.3250 +        };
143.3251 +    }
143.3252 +
143.3253 +    /**
143.3254 +     * Lay out this {@code BigDecimal} into a {@code char[]} array.
143.3255 +     * The Java 1.2 equivalent to this was called {@code getValueString}.
143.3256 +     *
143.3257 +     * @param  sci {@code true} for Scientific exponential notation;
143.3258 +     *          {@code false} for Engineering
143.3259 +     * @return string with canonical string representation of this
143.3260 +     *         {@code BigDecimal}
143.3261 +     */
143.3262 +    private String layoutChars(boolean sci) {
143.3263 +        if (scale == 0)                      // zero scale is trivial
143.3264 +            return (intCompact != INFLATED) ?
143.3265 +                Long.toString(intCompact):
143.3266 +                intVal.toString();
143.3267 +
143.3268 +        StringBuilderHelper sbHelper = StringBuilderHelper.INSTANCE;
143.3269 +        char[] coeff;
143.3270 +        int offset;  // offset is the starting index for coeff array
143.3271 +        // Get the significand as an absolute value
143.3272 +        if (intCompact != INFLATED) {
143.3273 +            offset = sbHelper.putIntCompact(Math.abs(intCompact));
143.3274 +            coeff  = sbHelper.getCompactCharArray();
143.3275 +        } else {
143.3276 +            offset = 0;
143.3277 +            coeff  = intVal.abs().toString().toCharArray();
143.3278 +        }
143.3279 +
143.3280 +        // Construct a buffer, with sufficient capacity for all cases.
143.3281 +        // If E-notation is needed, length will be: +1 if negative, +1
143.3282 +        // if '.' needed, +2 for "E+", + up to 10 for adjusted exponent.
143.3283 +        // Otherwise it could have +1 if negative, plus leading "0.00000"
143.3284 +        StringBuilder buf = sbHelper.getStringBuilder();
143.3285 +        if (signum() < 0)             // prefix '-' if negative
143.3286 +            buf.append('-');
143.3287 +        int coeffLen = coeff.length - offset;
143.3288 +        long adjusted = -(long)scale + (coeffLen -1);
143.3289 +        if ((scale >= 0) && (adjusted >= -6)) { // plain number
143.3290 +            int pad = scale - coeffLen;         // count of padding zeros
143.3291 +            if (pad >= 0) {                     // 0.xxx form
143.3292 +                buf.append('0');
143.3293 +                buf.append('.');
143.3294 +                for (; pad>0; pad--) {
143.3295 +                    buf.append('0');
143.3296 +                }
143.3297 +                buf.append(coeff, offset, coeffLen);
143.3298 +            } else {                         // xx.xx form
143.3299 +                buf.append(coeff, offset, -pad);
143.3300 +                buf.append('.');
143.3301 +                buf.append(coeff, -pad + offset, scale);
143.3302 +            }
143.3303 +        } else { // E-notation is needed
143.3304 +            if (sci) {                       // Scientific notation
143.3305 +                buf.append(coeff[offset]);   // first character
143.3306 +                if (coeffLen > 1) {          // more to come
143.3307 +                    buf.append('.');
143.3308 +                    buf.append(coeff, offset + 1, coeffLen - 1);
143.3309 +                }
143.3310 +            } else {                         // Engineering notation
143.3311 +                int sig = (int)(adjusted % 3);
143.3312 +                if (sig < 0)
143.3313 +                    sig += 3;                // [adjusted was negative]
143.3314 +                adjusted -= sig;             // now a multiple of 3
143.3315 +                sig++;
143.3316 +                if (signum() == 0) {
143.3317 +                    switch (sig) {
143.3318 +                    case 1:
143.3319 +                        buf.append('0'); // exponent is a multiple of three
143.3320 +                        break;
143.3321 +                    case 2:
143.3322 +                        buf.append("0.00");
143.3323 +                        adjusted += 3;
143.3324 +                        break;
143.3325 +                    case 3:
143.3326 +                        buf.append("0.0");
143.3327 +                        adjusted += 3;
143.3328 +                        break;
143.3329 +                    default:
143.3330 +                        throw new AssertionError("Unexpected sig value " + sig);
143.3331 +                    }
143.3332 +                } else if (sig >= coeffLen) {   // significand all in integer
143.3333 +                    buf.append(coeff, offset, coeffLen);
143.3334 +                    // may need some zeros, too
143.3335 +                    for (int i = sig - coeffLen; i > 0; i--)
143.3336 +                        buf.append('0');
143.3337 +                } else {                     // xx.xxE form
143.3338 +                    buf.append(coeff, offset, sig);
143.3339 +                    buf.append('.');
143.3340 +                    buf.append(coeff, offset + sig, coeffLen - sig);
143.3341 +                }
143.3342 +            }
143.3343 +            if (adjusted != 0) {             // [!sci could have made 0]
143.3344 +                buf.append('E');
143.3345 +                if (adjusted > 0)            // force sign for positive
143.3346 +                    buf.append('+');
143.3347 +                buf.append(adjusted);
143.3348 +            }
143.3349 +        }
143.3350 +        return buf.toString();
143.3351 +    }
143.3352 +
143.3353 +    /**
143.3354 +     * Return 10 to the power n, as a {@code BigInteger}.
143.3355 +     *
143.3356 +     * @param  n the power of ten to be returned (>=0)
143.3357 +     * @return a {@code BigInteger} with the value (10<sup>n</sup>)
143.3358 +     */
143.3359 +    private static BigInteger bigTenToThe(int n) {
143.3360 +        if (n < 0)
143.3361 +            return BigInteger.ZERO;
143.3362 +
143.3363 +        if (n < BIG_TEN_POWERS_TABLE_MAX) {
143.3364 +            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
143.3365 +            if (n < pows.length)
143.3366 +                return pows[n];
143.3367 +            else
143.3368 +                return expandBigIntegerTenPowers(n);
143.3369 +        }
143.3370 +        // BigInteger.pow is slow, so make 10**n by constructing a
143.3371 +        // BigInteger from a character string (still not very fast)
143.3372 +        char tenpow[] = new char[n + 1];
143.3373 +        tenpow[0] = '1';
143.3374 +        for (int i = 1; i <= n; i++)
143.3375 +            tenpow[i] = '0';
143.3376 +        return new BigInteger(tenpow);
143.3377 +    }
143.3378 +
143.3379 +    /**
143.3380 +     * Expand the BIG_TEN_POWERS_TABLE array to contain at least 10**n.
143.3381 +     *
143.3382 +     * @param n the power of ten to be returned (>=0)
143.3383 +     * @return a {@code BigDecimal} with the value (10<sup>n</sup>) and
143.3384 +     *         in the meantime, the BIG_TEN_POWERS_TABLE array gets
143.3385 +     *         expanded to the size greater than n.
143.3386 +     */
143.3387 +    private static BigInteger expandBigIntegerTenPowers(int n) {
143.3388 +        synchronized(BigDecimal.class) {
143.3389 +            BigInteger[] pows = BIG_TEN_POWERS_TABLE;
143.3390 +            int curLen = pows.length;
143.3391 +            // The following comparison and the above synchronized statement is
143.3392 +            // to prevent multiple threads from expanding the same array.
143.3393 +            if (curLen <= n) {
143.3394 +                int newLen = curLen << 1;
143.3395 +                while (newLen <= n)
143.3396 +                    newLen <<= 1;
143.3397 +                pows = Arrays.copyOf(pows, newLen);
143.3398 +                for (int i = curLen; i < newLen; i++)
143.3399 +                    pows[i] = pows[i - 1].multiply(BigInteger.TEN);
143.3400 +                // Based on the following facts:
143.3401 +                // 1. pows is a private local varible;
143.3402 +                // 2. the following store is a volatile store.
143.3403 +                // the newly created array elements can be safely published.
143.3404 +                BIG_TEN_POWERS_TABLE = pows;
143.3405 +            }
143.3406 +            return pows[n];
143.3407 +        }
143.3408 +    }
143.3409 +
143.3410 +    private static final long[] LONG_TEN_POWERS_TABLE = {
143.3411 +        1,                     // 0 / 10^0
143.3412 +        10,                    // 1 / 10^1
143.3413 +        100,                   // 2 / 10^2
143.3414 +        1000,                  // 3 / 10^3
143.3415 +        10000,                 // 4 / 10^4
143.3416 +        100000,                // 5 / 10^5
143.3417 +        1000000,               // 6 / 10^6
143.3418 +        10000000,              // 7 / 10^7
143.3419 +        100000000,             // 8 / 10^8
143.3420 +        1000000000,            // 9 / 10^9
143.3421 +        10000000000L,          // 10 / 10^10
143.3422 +        100000000000L,         // 11 / 10^11
143.3423 +        1000000000000L,        // 12 / 10^12
143.3424 +        10000000000000L,       // 13 / 10^13
143.3425 +        100000000000000L,      // 14 / 10^14
143.3426 +        1000000000000000L,     // 15 / 10^15
143.3427 +        10000000000000000L,    // 16 / 10^16
143.3428 +        100000000000000000L,   // 17 / 10^17
143.3429 +        1000000000000000000L   // 18 / 10^18
143.3430 +    };
143.3431 +
143.3432 +    private static volatile BigInteger BIG_TEN_POWERS_TABLE[] = {BigInteger.ONE,
143.3433 +        BigInteger.valueOf(10),       BigInteger.valueOf(100),
143.3434 +        BigInteger.valueOf(1000),     BigInteger.valueOf(10000),
143.3435 +        BigInteger.valueOf(100000),   BigInteger.valueOf(1000000),
143.3436 +        BigInteger.valueOf(10000000), BigInteger.valueOf(100000000),
143.3437 +        BigInteger.valueOf(1000000000),
143.3438 +        BigInteger.valueOf(10000000000L),
143.3439 +        BigInteger.valueOf(100000000000L),
143.3440 +        BigInteger.valueOf(1000000000000L),
143.3441 +        BigInteger.valueOf(10000000000000L),
143.3442 +        BigInteger.valueOf(100000000000000L),
143.3443 +        BigInteger.valueOf(1000000000000000L),
143.3444 +        BigInteger.valueOf(10000000000000000L),
143.3445 +        BigInteger.valueOf(100000000000000000L),
143.3446 +        BigInteger.valueOf(1000000000000000000L)
143.3447 +    };
143.3448 +
143.3449 +    private static final int BIG_TEN_POWERS_TABLE_INITLEN =
143.3450 +        BIG_TEN_POWERS_TABLE.length;
143.3451 +    private static final int BIG_TEN_POWERS_TABLE_MAX =
143.3452 +        16 * BIG_TEN_POWERS_TABLE_INITLEN;
143.3453 +
143.3454 +    private static final long THRESHOLDS_TABLE[] = {
143.3455 +        Long.MAX_VALUE,                     // 0
143.3456 +        Long.MAX_VALUE/10L,                 // 1
143.3457 +        Long.MAX_VALUE/100L,                // 2
143.3458 +        Long.MAX_VALUE/1000L,               // 3
143.3459 +        Long.MAX_VALUE/10000L,              // 4
143.3460 +        Long.MAX_VALUE/100000L,             // 5
143.3461 +        Long.MAX_VALUE/1000000L,            // 6
143.3462 +        Long.MAX_VALUE/10000000L,           // 7
143.3463 +        Long.MAX_VALUE/100000000L,          // 8
143.3464 +        Long.MAX_VALUE/1000000000L,         // 9
143.3465 +        Long.MAX_VALUE/10000000000L,        // 10
143.3466 +        Long.MAX_VALUE/100000000000L,       // 11
143.3467 +        Long.MAX_VALUE/1000000000000L,      // 12
143.3468 +        Long.MAX_VALUE/10000000000000L,     // 13
143.3469 +        Long.MAX_VALUE/100000000000000L,    // 14
143.3470 +        Long.MAX_VALUE/1000000000000000L,   // 15
143.3471 +        Long.MAX_VALUE/10000000000000000L,  // 16
143.3472 +        Long.MAX_VALUE/100000000000000000L, // 17
143.3473 +        Long.MAX_VALUE/1000000000000000000L // 18
143.3474 +    };
143.3475 +
143.3476 +    /**
143.3477 +     * Compute val * 10 ^ n; return this product if it is
143.3478 +     * representable as a long, INFLATED otherwise.
143.3479 +     */
143.3480 +    private static long longMultiplyPowerTen(long val, int n) {
143.3481 +        if (val == 0 || n <= 0)
143.3482 +            return val;
143.3483 +        long[] tab = LONG_TEN_POWERS_TABLE;
143.3484 +        long[] bounds = THRESHOLDS_TABLE;
143.3485 +        if (n < tab.length && n < bounds.length) {
143.3486 +            long tenpower = tab[n];
143.3487 +            if (val == 1)
143.3488 +                return tenpower;
143.3489 +            if (Math.abs(val) <= bounds[n])
143.3490 +                return val * tenpower;
143.3491 +        }
143.3492 +        return INFLATED;
143.3493 +    }
143.3494 +
143.3495 +    /**
143.3496 +     * Compute this * 10 ^ n.
143.3497 +     * Needed mainly to allow special casing to trap zero value
143.3498 +     */
143.3499 +    private BigInteger bigMultiplyPowerTen(int n) {
143.3500 +        if (n <= 0)
143.3501 +            return this.inflate();
143.3502 +
143.3503 +        if (intCompact != INFLATED)
143.3504 +            return bigTenToThe(n).multiply(intCompact);
143.3505 +        else
143.3506 +            return intVal.multiply(bigTenToThe(n));
143.3507 +    }
143.3508 +
143.3509 +    /**
143.3510 +     * Assign appropriate BigInteger to intVal field if intVal is
143.3511 +     * null, i.e. the compact representation is in use.
143.3512 +     */
143.3513 +    private BigInteger inflate() {
143.3514 +        if (intVal == null)
143.3515 +            intVal = BigInteger.valueOf(intCompact);
143.3516 +        return intVal;
143.3517 +    }
143.3518 +
143.3519 +    /**
143.3520 +     * Match the scales of two {@code BigDecimal}s to align their
143.3521 +     * least significant digits.
143.3522 +     *
143.3523 +     * <p>If the scales of val[0] and val[1] differ, rescale
143.3524 +     * (non-destructively) the lower-scaled {@code BigDecimal} so
143.3525 +     * they match.  That is, the lower-scaled reference will be
143.3526 +     * replaced by a reference to a new object with the same scale as
143.3527 +     * the other {@code BigDecimal}.
143.3528 +     *
143.3529 +     * @param  val array of two elements referring to the two
143.3530 +     *         {@code BigDecimal}s to be aligned.
143.3531 +     */
143.3532 +    private static void matchScale(BigDecimal[] val) {
143.3533 +        if (val[0].scale == val[1].scale) {
143.3534 +            return;
143.3535 +        } else if (val[0].scale < val[1].scale) {
143.3536 +            val[0] = val[0].setScale(val[1].scale, ROUND_UNNECESSARY);
143.3537 +        } else if (val[1].scale < val[0].scale) {
143.3538 +            val[1] = val[1].setScale(val[0].scale, ROUND_UNNECESSARY);
143.3539 +        }
143.3540 +    }
143.3541 +
143.3542 +    /**
143.3543 +     * Reconstitute the {@code BigDecimal} instance from a stream (that is,
143.3544 +     * deserialize it).
143.3545 +     *
143.3546 +     * @param s the stream being read.
143.3547 +     */
143.3548 +    private void readObject(java.io.ObjectInputStream s)
143.3549 +        throws java.io.IOException, ClassNotFoundException {
143.3550 +        // Read in all fields
143.3551 +        s.defaultReadObject();
143.3552 +        // validate possibly bad fields
143.3553 +        if (intVal == null) {
143.3554 +            String message = "BigDecimal: null intVal in stream";
143.3555 +            throw new java.io.StreamCorruptedException(message);
143.3556 +        // [all values of scale are now allowed]
143.3557 +        }
143.3558 +        intCompact = compactValFor(intVal);
143.3559 +    }
143.3560 +
143.3561 +   /**
143.3562 +    * Serialize this {@code BigDecimal} to the stream in question
143.3563 +    *
143.3564 +    * @param s the stream to serialize to.
143.3565 +    */
143.3566 +   private void writeObject(java.io.ObjectOutputStream s)
143.3567 +       throws java.io.IOException {
143.3568 +       // Must inflate to maintain compatible serial form.
143.3569 +       this.inflate();
143.3570 +
143.3571 +       // Write proper fields
143.3572 +       s.defaultWriteObject();
143.3573 +   }
143.3574 +
143.3575 +
143.3576 +    /**
143.3577 +     * Returns the length of the absolute value of a {@code long}, in decimal
143.3578 +     * digits.
143.3579 +     *
143.3580 +     * @param x the {@code long}
143.3581 +     * @return the length of the unscaled value, in deciaml digits.
143.3582 +     */
143.3583 +    private static int longDigitLength(long x) {
143.3584 +        /*
143.3585 +         * As described in "Bit Twiddling Hacks" by Sean Anderson,
143.3586 +         * (http://graphics.stanford.edu/~seander/bithacks.html)
143.3587 +         * integer log 10 of x is within 1 of
143.3588 +         * (1233/4096)* (1 + integer log 2 of x).
143.3589 +         * The fraction 1233/4096 approximates log10(2). So we first
143.3590 +         * do a version of log2 (a variant of Long class with
143.3591 +         * pre-checks and opposite directionality) and then scale and
143.3592 +         * check against powers table. This is a little simpler in
143.3593 +         * present context than the version in Hacker's Delight sec
143.3594 +         * 11-4.  Adding one to bit length allows comparing downward
143.3595 +         * from the LONG_TEN_POWERS_TABLE that we need anyway.
143.3596 +         */
143.3597 +        assert x != INFLATED;
143.3598 +        if (x < 0)
143.3599 +            x = -x;
143.3600 +        if (x < 10) // must screen for 0, might as well 10
143.3601 +            return 1;
143.3602 +        int n = 64; // not 63, to avoid needing to add 1 later
143.3603 +        int y = (int)(x >>> 32);
143.3604 +        if (y == 0) { n -= 32; y = (int)x; }
143.3605 +        if (y >>> 16 == 0) { n -= 16; y <<= 16; }
143.3606 +        if (y >>> 24 == 0) { n -=  8; y <<=  8; }
143.3607 +        if (y >>> 28 == 0) { n -=  4; y <<=  4; }
143.3608 +        if (y >>> 30 == 0) { n -=  2; y <<=  2; }
143.3609 +        int r = (((y >>> 31) + n) * 1233) >>> 12;
143.3610 +        long[] tab = LONG_TEN_POWERS_TABLE;
143.3611 +        // if r >= length, must have max possible digits for long
143.3612 +        return (r >= tab.length || x < tab[r])? r : r+1;
143.3613 +    }
143.3614 +
143.3615 +    /**
143.3616 +     * Returns the length of the absolute value of a BigInteger, in
143.3617 +     * decimal digits.
143.3618 +     *
143.3619 +     * @param b the BigInteger
143.3620 +     * @return the length of the unscaled value, in decimal digits
143.3621 +     */
143.3622 +    private static int bigDigitLength(BigInteger b) {
143.3623 +        /*
143.3624 +         * Same idea as the long version, but we need a better
143.3625 +         * approximation of log10(2). Using 646456993/2^31
143.3626 +         * is accurate up to max possible reported bitLength.
143.3627 +         */
143.3628 +        if (b.signum == 0)
143.3629 +            return 1;
143.3630 +        int r = (int)((((long)b.bitLength() + 1) * 646456993) >>> 31);
143.3631 +        return b.compareMagnitude(bigTenToThe(r)) < 0? r : r+1;
143.3632 +    }
143.3633 +
143.3634 +
143.3635 +    /**
143.3636 +     * Remove insignificant trailing zeros from this
143.3637 +     * {@code BigDecimal} until the preferred scale is reached or no
143.3638 +     * more zeros can be removed.  If the preferred scale is less than
143.3639 +     * Integer.MIN_VALUE, all the trailing zeros will be removed.
143.3640 +     *
143.3641 +     * {@code BigInteger} assistance could help, here?
143.3642 +     *
143.3643 +     * <p>WARNING: This method should only be called on new objects as
143.3644 +     * it mutates the value fields.
143.3645 +     *
143.3646 +     * @return this {@code BigDecimal} with a scale possibly reduced
143.3647 +     * to be closed to the preferred scale.
143.3648 +     */
143.3649 +    private BigDecimal stripZerosToMatchScale(long preferredScale) {
143.3650 +        this.inflate();
143.3651 +        BigInteger qr[];                // quotient-remainder pair
143.3652 +        while ( intVal.compareMagnitude(BigInteger.TEN) >= 0 &&
143.3653 +                scale > preferredScale) {
143.3654 +            if (intVal.testBit(0))
143.3655 +                break;                  // odd number cannot end in 0
143.3656 +            qr = intVal.divideAndRemainder(BigInteger.TEN);
143.3657 +            if (qr[1].signum() != 0)
143.3658 +                break;                  // non-0 remainder
143.3659 +            intVal=qr[0];
143.3660 +            scale = checkScale((long)scale-1);  // could Overflow
143.3661 +            if (precision > 0)          // adjust precision if known
143.3662 +              precision--;
143.3663 +        }
143.3664 +        if (intVal != null)
143.3665 +            intCompact = compactValFor(intVal);
143.3666 +        return this;
143.3667 +    }
143.3668 +
143.3669 +    /**
143.3670 +     * Check a scale for Underflow or Overflow.  If this BigDecimal is
143.3671 +     * nonzero, throw an exception if the scale is outof range. If this
143.3672 +     * is zero, saturate the scale to the extreme value of the right
143.3673 +     * sign if the scale is out of range.
143.3674 +     *
143.3675 +     * @param val The new scale.
143.3676 +     * @throws ArithmeticException (overflow or underflow) if the new
143.3677 +     *         scale is out of range.
143.3678 +     * @return validated scale as an int.
143.3679 +     */
143.3680 +    private int checkScale(long val) {
143.3681 +        int asInt = (int)val;
143.3682 +        if (asInt != val) {
143.3683 +            asInt = val>Integer.MAX_VALUE ? Integer.MAX_VALUE : Integer.MIN_VALUE;
143.3684 +            BigInteger b;
143.3685 +            if (intCompact != 0 &&
143.3686 +                ((b = intVal) == null || b.signum() != 0))
143.3687 +                throw new ArithmeticException(asInt>0 ? "Underflow":"Overflow");
143.3688 +        }
143.3689 +        return asInt;
143.3690 +    }
143.3691 +
143.3692 +    /**
143.3693 +     * Round an operand; used only if digits &gt; 0.  Does not change
143.3694 +     * {@code this}; if rounding is needed a new {@code BigDecimal}
143.3695 +     * is created and returned.
143.3696 +     *
143.3697 +     * @param mc the context to use.
143.3698 +     * @throws ArithmeticException if the result is inexact but the
143.3699 +     *         rounding mode is {@code UNNECESSARY}.
143.3700 +     */
143.3701 +    private BigDecimal roundOp(MathContext mc) {
143.3702 +        BigDecimal rounded = doRound(this, mc);
143.3703 +        return rounded;
143.3704 +    }
143.3705 +
143.3706 +    /** Round this BigDecimal according to the MathContext settings;
143.3707 +     *  used only if precision {@literal >} 0.
143.3708 +     *
143.3709 +     * <p>WARNING: This method should only be called on new objects as
143.3710 +     * it mutates the value fields.
143.3711 +     *
143.3712 +     * @param mc the context to use.
143.3713 +     * @throws ArithmeticException if the rounding mode is
143.3714 +     *         {@code RoundingMode.UNNECESSARY} and the
143.3715 +     *         {@code BigDecimal} operation would require rounding.
143.3716 +     */
143.3717 +    private void roundThis(MathContext mc) {
143.3718 +        BigDecimal rounded = doRound(this, mc);
143.3719 +        if (rounded == this)                 // wasn't rounded
143.3720 +            return;
143.3721 +        this.intVal     = rounded.intVal;
143.3722 +        this.intCompact = rounded.intCompact;
143.3723 +        this.scale      = rounded.scale;
143.3724 +        this.precision  = rounded.precision;
143.3725 +    }
143.3726 +
143.3727 +    /**
143.3728 +     * Returns a {@code BigDecimal} rounded according to the
143.3729 +     * MathContext settings; used only if {@code mc.precision > 0}.
143.3730 +     * Does not change {@code this}; if rounding is needed a new
143.3731 +     * {@code BigDecimal} is created and returned.
143.3732 +     *
143.3733 +     * @param mc the context to use.
143.3734 +     * @return a {@code BigDecimal} rounded according to the MathContext
143.3735 +     *         settings.  May return this, if no rounding needed.
143.3736 +     * @throws ArithmeticException if the rounding mode is
143.3737 +     *         {@code RoundingMode.UNNECESSARY} and the
143.3738 +     *         result is inexact.
143.3739 +     */
143.3740 +    private static BigDecimal doRound(BigDecimal d, MathContext mc) {
143.3741 +        int mcp = mc.precision;
143.3742 +        int drop;
143.3743 +        // This might (rarely) iterate to cover the 999=>1000 case
143.3744 +        while ((drop = d.precision() - mcp) > 0) {
143.3745 +            int newScale = d.checkScale((long)d.scale - drop);
143.3746 +            int mode = mc.roundingMode.oldMode;
143.3747 +            if (drop < LONG_TEN_POWERS_TABLE.length)
143.3748 +                d = divideAndRound(d.intCompact, d.intVal,
143.3749 +                                   LONG_TEN_POWERS_TABLE[drop], null,
143.3750 +                                   newScale, mode, newScale);
143.3751 +            else
143.3752 +                d = divideAndRound(d.intCompact, d.intVal,
143.3753 +                                   INFLATED, bigTenToThe(drop),
143.3754 +                                   newScale, mode, newScale);
143.3755 +        }
143.3756 +        return d;
143.3757 +    }
143.3758 +
143.3759 +    /**
143.3760 +     * Returns the compact value for given {@code BigInteger}, or
143.3761 +     * INFLATED if too big. Relies on internal representation of
143.3762 +     * {@code BigInteger}.
143.3763 +     */
143.3764 +    private static long compactValFor(BigInteger b) {
143.3765 +        int[] m = b.mag;
143.3766 +        int len = m.length;
143.3767 +        if (len == 0)
143.3768 +            return 0;
143.3769 +        int d = m[0];
143.3770 +        if (len > 2 || (len == 2 && d < 0))
143.3771 +            return INFLATED;
143.3772 +
143.3773 +        long u = (len == 2)?
143.3774 +            (((long) m[1] & LONG_MASK) + (((long)d) << 32)) :
143.3775 +            (((long)d)   & LONG_MASK);
143.3776 +        return (b.signum < 0)? -u : u;
143.3777 +    }
143.3778 +
143.3779 +    private static int longCompareMagnitude(long x, long y) {
143.3780 +        if (x < 0)
143.3781 +            x = -x;
143.3782 +        if (y < 0)
143.3783 +            y = -y;
143.3784 +        return (x < y) ? -1 : ((x == y) ? 0 : 1);
143.3785 +    }
143.3786 +
143.3787 +    private static int saturateLong(long s) {
143.3788 +        int i = (int)s;
143.3789 +        return (s == i) ? i : (s < 0 ? Integer.MIN_VALUE : Integer.MAX_VALUE);
143.3790 +    }
143.3791 +
143.3792 +    /*
143.3793 +     * Internal printing routine
143.3794 +     */
143.3795 +    private static void print(String name, BigDecimal bd) {
143.3796 +    }
143.3797 +
143.3798 +    /**
143.3799 +     * Check internal invariants of this BigDecimal.  These invariants
143.3800 +     * include:
143.3801 +     *
143.3802 +     * <ul>
143.3803 +     *
143.3804 +     * <li>The object must be initialized; either intCompact must not be
143.3805 +     * INFLATED or intVal is non-null.  Both of these conditions may
143.3806 +     * be true.
143.3807 +     *
143.3808 +     * <li>If both intCompact and intVal and set, their values must be
143.3809 +     * consistent.
143.3810 +     *
143.3811 +     * <li>If precision is nonzero, it must have the right value.
143.3812 +     * </ul>
143.3813 +     *
143.3814 +     * Note: Since this is an audit method, we are not supposed to change the
143.3815 +     * state of this BigDecimal object.
143.3816 +     */
143.3817 +    private BigDecimal audit() {
143.3818 +        if (intCompact == INFLATED) {
143.3819 +            if (intVal == null) {
143.3820 +                print("audit", this);
143.3821 +                throw new AssertionError("null intVal");
143.3822 +            }
143.3823 +            // Check precision
143.3824 +            if (precision > 0 && precision != bigDigitLength(intVal)) {
143.3825 +                print("audit", this);
143.3826 +                throw new AssertionError("precision mismatch");
143.3827 +            }
143.3828 +        } else {
143.3829 +            if (intVal != null) {
143.3830 +                long val = intVal.longValue();
143.3831 +                if (val != intCompact) {
143.3832 +                    print("audit", this);
143.3833 +                    throw new AssertionError("Inconsistent state, intCompact=" +
143.3834 +                                             intCompact + "\t intVal=" + val);
143.3835 +                }
143.3836 +            }
143.3837 +            // Check precision
143.3838 +            if (precision > 0 && precision != longDigitLength(intCompact)) {
143.3839 +                print("audit", this);
143.3840 +                throw new AssertionError("precision mismatch");
143.3841 +            }
143.3842 +        }
143.3843 +        return this;
143.3844 +    }
143.3845 +}
   144.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   144.2 +++ b/rt/emul/compact/src/main/java/java/math/BigInteger.java	Mon Oct 07 14:20:58 2013 +0200
   144.3 @@ -0,0 +1,3122 @@
   144.4 +/*
   144.5 + * Copyright (c) 1996, 2007, Oracle and/or its affiliates. All rights reserved.
   144.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   144.7 + *
   144.8 + * This code is free software; you can redistribute it and/or modify it
   144.9 + * under the terms of the GNU General Public License version 2 only, as
  144.10 + * published by the Free Software Foundation.  Oracle designates this
  144.11 + * particular file as subject to the "Classpath" exception as provided
  144.12 + * by Oracle in the LICENSE file that accompanied this code.
  144.13 + *
  144.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  144.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  144.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  144.17 + * version 2 for more details (a copy is included in the LICENSE file that
  144.18 + * accompanied this code).
  144.19 + *
  144.20 + * You should have received a copy of the GNU General Public License version
  144.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  144.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  144.23 + *
  144.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  144.25 + * or visit www.oracle.com if you need additional information or have any
  144.26 + * questions.
  144.27 + */
  144.28 +
  144.29 +/*
  144.30 + * Portions Copyright (c) 1995  Colin Plumb.  All rights reserved.
  144.31 + */
  144.32 +
  144.33 +package java.math;
  144.34 +
  144.35 +import java.util.Random;
  144.36 +import java.io.*;
  144.37 +
  144.38 +/**
  144.39 + * Immutable arbitrary-precision integers.  All operations behave as if
  144.40 + * BigIntegers were represented in two's-complement notation (like Java's
  144.41 + * primitive integer types).  BigInteger provides analogues to all of Java's
  144.42 + * primitive integer operators, and all relevant methods from java.lang.Math.
  144.43 + * Additionally, BigInteger provides operations for modular arithmetic, GCD
  144.44 + * calculation, primality testing, prime generation, bit manipulation,
  144.45 + * and a few other miscellaneous operations.
  144.46 + *
  144.47 + * <p>Semantics of arithmetic operations exactly mimic those of Java's integer
  144.48 + * arithmetic operators, as defined in <i>The Java Language Specification</i>.
  144.49 + * For example, division by zero throws an {@code ArithmeticException}, and
  144.50 + * division of a negative by a positive yields a negative (or zero) remainder.
  144.51 + * All of the details in the Spec concerning overflow are ignored, as
  144.52 + * BigIntegers are made as large as necessary to accommodate the results of an
  144.53 + * operation.
  144.54 + *
  144.55 + * <p>Semantics of shift operations extend those of Java's shift operators
  144.56 + * to allow for negative shift distances.  A right-shift with a negative
  144.57 + * shift distance results in a left shift, and vice-versa.  The unsigned
  144.58 + * right shift operator ({@code >>>}) is omitted, as this operation makes
  144.59 + * little sense in combination with the "infinite word size" abstraction
  144.60 + * provided by this class.
  144.61 + *
  144.62 + * <p>Semantics of bitwise logical operations exactly mimic those of Java's
  144.63 + * bitwise integer operators.  The binary operators ({@code and},
  144.64 + * {@code or}, {@code xor}) implicitly perform sign extension on the shorter
  144.65 + * of the two operands prior to performing the operation.
  144.66 + *
  144.67 + * <p>Comparison operations perform signed integer comparisons, analogous to
  144.68 + * those performed by Java's relational and equality operators.
  144.69 + *
  144.70 + * <p>Modular arithmetic operations are provided to compute residues, perform
  144.71 + * exponentiation, and compute multiplicative inverses.  These methods always
  144.72 + * return a non-negative result, between {@code 0} and {@code (modulus - 1)},
  144.73 + * inclusive.
  144.74 + *
  144.75 + * <p>Bit operations operate on a single bit of the two's-complement
  144.76 + * representation of their operand.  If necessary, the operand is sign-
  144.77 + * extended so that it contains the designated bit.  None of the single-bit
  144.78 + * operations can produce a BigInteger with a different sign from the
  144.79 + * BigInteger being operated on, as they affect only a single bit, and the
  144.80 + * "infinite word size" abstraction provided by this class ensures that there
  144.81 + * are infinitely many "virtual sign bits" preceding each BigInteger.
  144.82 + *
  144.83 + * <p>For the sake of brevity and clarity, pseudo-code is used throughout the
  144.84 + * descriptions of BigInteger methods.  The pseudo-code expression
  144.85 + * {@code (i + j)} is shorthand for "a BigInteger whose value is
  144.86 + * that of the BigInteger {@code i} plus that of the BigInteger {@code j}."
  144.87 + * The pseudo-code expression {@code (i == j)} is shorthand for
  144.88 + * "{@code true} if and only if the BigInteger {@code i} represents the same
  144.89 + * value as the BigInteger {@code j}."  Other pseudo-code expressions are
  144.90 + * interpreted similarly.
  144.91 + *
  144.92 + * <p>All methods and constructors in this class throw
  144.93 + * {@code NullPointerException} when passed
  144.94 + * a null object reference for any input parameter.
  144.95 + *
  144.96 + * @see     BigDecimal
  144.97 + * @author  Josh Bloch
  144.98 + * @author  Michael McCloskey
  144.99 + * @since JDK1.1
 144.100 + */
 144.101 +
 144.102 +public class BigInteger extends Number implements Comparable<BigInteger> {
 144.103 +    /**
 144.104 +     * The signum of this BigInteger: -1 for negative, 0 for zero, or
 144.105 +     * 1 for positive.  Note that the BigInteger zero <i>must</i> have
 144.106 +     * a signum of 0.  This is necessary to ensures that there is exactly one
 144.107 +     * representation for each BigInteger value.
 144.108 +     *
 144.109 +     * @serial
 144.110 +     */
 144.111 +    final int signum;
 144.112 +
 144.113 +    /**
 144.114 +     * The magnitude of this BigInteger, in <i>big-endian</i> order: the
 144.115 +     * zeroth element of this array is the most-significant int of the
 144.116 +     * magnitude.  The magnitude must be "minimal" in that the most-significant
 144.117 +     * int ({@code mag[0]}) must be non-zero.  This is necessary to
 144.118 +     * ensure that there is exactly one representation for each BigInteger
 144.119 +     * value.  Note that this implies that the BigInteger zero has a
 144.120 +     * zero-length mag array.
 144.121 +     */
 144.122 +    final int[] mag;
 144.123 +
 144.124 +    // These "redundant fields" are initialized with recognizable nonsense
 144.125 +    // values, and cached the first time they are needed (or never, if they
 144.126 +    // aren't needed).
 144.127 +
 144.128 +     /**
 144.129 +     * One plus the bitCount of this BigInteger. Zeros means unitialized.
 144.130 +     *
 144.131 +     * @serial
 144.132 +     * @see #bitCount
 144.133 +     * @deprecated Deprecated since logical value is offset from stored
 144.134 +     * value and correction factor is applied in accessor method.
 144.135 +     */
 144.136 +    @Deprecated
 144.137 +    private int bitCount;
 144.138 +
 144.139 +    /**
 144.140 +     * One plus the bitLength of this BigInteger. Zeros means unitialized.
 144.141 +     * (either value is acceptable).
 144.142 +     *
 144.143 +     * @serial
 144.144 +     * @see #bitLength()
 144.145 +     * @deprecated Deprecated since logical value is offset from stored
 144.146 +     * value and correction factor is applied in accessor method.
 144.147 +     */
 144.148 +    @Deprecated
 144.149 +    private int bitLength;
 144.150 +
 144.151 +    /**
 144.152 +     * Two plus the lowest set bit of this BigInteger, as returned by
 144.153 +     * getLowestSetBit().
 144.154 +     *
 144.155 +     * @serial
 144.156 +     * @see #getLowestSetBit
 144.157 +     * @deprecated Deprecated since logical value is offset from stored
 144.158 +     * value and correction factor is applied in accessor method.
 144.159 +     */
 144.160 +    @Deprecated
 144.161 +    private int lowestSetBit;
 144.162 +
 144.163 +    /**
 144.164 +     * Two plus the index of the lowest-order int in the magnitude of this
 144.165 +     * BigInteger that contains a nonzero int, or -2 (either value is acceptable).
 144.166 +     * The least significant int has int-number 0, the next int in order of
 144.167 +     * increasing significance has int-number 1, and so forth.
 144.168 +     * @deprecated Deprecated since logical value is offset from stored
 144.169 +     * value and correction factor is applied in accessor method.
 144.170 +     */
 144.171 +    @Deprecated
 144.172 +    private int firstNonzeroIntNum;
 144.173 +
 144.174 +    /**
 144.175 +     * This mask is used to obtain the value of an int as if it were unsigned.
 144.176 +     */
 144.177 +    final static long LONG_MASK = 0xffffffffL;
 144.178 +
 144.179 +    //Constructors
 144.180 +
 144.181 +    /**
 144.182 +     * Translates a byte array containing the two's-complement binary
 144.183 +     * representation of a BigInteger into a BigInteger.  The input array is
 144.184 +     * assumed to be in <i>big-endian</i> byte-order: the most significant
 144.185 +     * byte is in the zeroth element.
 144.186 +     *
 144.187 +     * @param  val big-endian two's-complement binary representation of
 144.188 +     *         BigInteger.
 144.189 +     * @throws NumberFormatException {@code val} is zero bytes long.
 144.190 +     */
 144.191 +    public BigInteger(byte[] val) {
 144.192 +        if (val.length == 0)
 144.193 +            throw new NumberFormatException("Zero length BigInteger");
 144.194 +
 144.195 +        if (val[0] < 0) {
 144.196 +            mag = makePositive(val);
 144.197 +            signum = -1;
 144.198 +        } else {
 144.199 +            mag = stripLeadingZeroBytes(val);
 144.200 +            signum = (mag.length == 0 ? 0 : 1);
 144.201 +        }
 144.202 +    }
 144.203 +
 144.204 +    /**
 144.205 +     * This private constructor translates an int array containing the
 144.206 +     * two's-complement binary representation of a BigInteger into a
 144.207 +     * BigInteger. The input array is assumed to be in <i>big-endian</i>
 144.208 +     * int-order: the most significant int is in the zeroth element.
 144.209 +     */
 144.210 +    private BigInteger(int[] val) {
 144.211 +        if (val.length == 0)
 144.212 +            throw new NumberFormatException("Zero length BigInteger");
 144.213 +
 144.214 +        if (val[0] < 0) {
 144.215 +            mag = makePositive(val);
 144.216 +            signum = -1;
 144.217 +        } else {
 144.218 +            mag = trustedStripLeadingZeroInts(val);
 144.219 +            signum = (mag.length == 0 ? 0 : 1);
 144.220 +        }
 144.221 +    }
 144.222 +
 144.223 +    /**
 144.224 +     * Translates the sign-magnitude representation of a BigInteger into a
 144.225 +     * BigInteger.  The sign is represented as an integer signum value: -1 for
 144.226 +     * negative, 0 for zero, or 1 for positive.  The magnitude is a byte array
 144.227 +     * in <i>big-endian</i> byte-order: the most significant byte is in the
 144.228 +     * zeroth element.  A zero-length magnitude array is permissible, and will
 144.229 +     * result in a BigInteger value of 0, whether signum is -1, 0 or 1.
 144.230 +     *
 144.231 +     * @param  signum signum of the number (-1 for negative, 0 for zero, 1
 144.232 +     *         for positive).
 144.233 +     * @param  magnitude big-endian binary representation of the magnitude of
 144.234 +     *         the number.
 144.235 +     * @throws NumberFormatException {@code signum} is not one of the three
 144.236 +     *         legal values (-1, 0, and 1), or {@code signum} is 0 and
 144.237 +     *         {@code magnitude} contains one or more non-zero bytes.
 144.238 +     */
 144.239 +    public BigInteger(int signum, byte[] magnitude) {
 144.240 +        this.mag = stripLeadingZeroBytes(magnitude);
 144.241 +
 144.242 +        if (signum < -1 || signum > 1)
 144.243 +            throw(new NumberFormatException("Invalid signum value"));
 144.244 +
 144.245 +        if (this.mag.length==0) {
 144.246 +            this.signum = 0;
 144.247 +        } else {
 144.248 +            if (signum == 0)
 144.249 +                throw(new NumberFormatException("signum-magnitude mismatch"));
 144.250 +            this.signum = signum;
 144.251 +        }
 144.252 +    }
 144.253 +
 144.254 +    /**
 144.255 +     * A constructor for internal use that translates the sign-magnitude
 144.256 +     * representation of a BigInteger into a BigInteger. It checks the
 144.257 +     * arguments and copies the magnitude so this constructor would be
 144.258 +     * safe for external use.
 144.259 +     */
 144.260 +    private BigInteger(int signum, int[] magnitude) {
 144.261 +        this.mag = stripLeadingZeroInts(magnitude);
 144.262 +
 144.263 +        if (signum < -1 || signum > 1)
 144.264 +            throw(new NumberFormatException("Invalid signum value"));
 144.265 +
 144.266 +        if (this.mag.length==0) {
 144.267 +            this.signum = 0;
 144.268 +        } else {
 144.269 +            if (signum == 0)
 144.270 +                throw(new NumberFormatException("signum-magnitude mismatch"));
 144.271 +            this.signum = signum;
 144.272 +        }
 144.273 +    }
 144.274 +
 144.275 +    /**
 144.276 +     * Translates the String representation of a BigInteger in the
 144.277 +     * specified radix into a BigInteger.  The String representation
 144.278 +     * consists of an optional minus or plus sign followed by a
 144.279 +     * sequence of one or more digits in the specified radix.  The
 144.280 +     * character-to-digit mapping is provided by {@code
 144.281 +     * Character.digit}.  The String may not contain any extraneous
 144.282 +     * characters (whitespace, for example).
 144.283 +     *
 144.284 +     * @param val String representation of BigInteger.
 144.285 +     * @param radix radix to be used in interpreting {@code val}.
 144.286 +     * @throws NumberFormatException {@code val} is not a valid representation
 144.287 +     *         of a BigInteger in the specified radix, or {@code radix} is
 144.288 +     *         outside the range from {@link Character#MIN_RADIX} to
 144.289 +     *         {@link Character#MAX_RADIX}, inclusive.
 144.290 +     * @see    Character#digit
 144.291 +     */
 144.292 +    public BigInteger(String val, int radix) {
 144.293 +        int cursor = 0, numDigits;
 144.294 +        final int len = val.length();
 144.295 +
 144.296 +        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
 144.297 +            throw new NumberFormatException("Radix out of range");
 144.298 +        if (len == 0)
 144.299 +            throw new NumberFormatException("Zero length BigInteger");
 144.300 +
 144.301 +        // Check for at most one leading sign
 144.302 +        int sign = 1;
 144.303 +        int index1 = val.lastIndexOf('-');
 144.304 +        int index2 = val.lastIndexOf('+');
 144.305 +        if ((index1 + index2) <= -1) {
 144.306 +            // No leading sign character or at most one leading sign character
 144.307 +            if (index1 == 0 || index2 == 0) {
 144.308 +                cursor = 1;
 144.309 +                if (len == 1)
 144.310 +                    throw new NumberFormatException("Zero length BigInteger");
 144.311 +            }
 144.312 +            if (index1 == 0)
 144.313 +                sign = -1;
 144.314 +        } else
 144.315 +            throw new NumberFormatException("Illegal embedded sign character");
 144.316 +
 144.317 +        // Skip leading zeros and compute number of digits in magnitude
 144.318 +        while (cursor < len &&
 144.319 +               Character.digit(val.charAt(cursor), radix) == 0)
 144.320 +            cursor++;
 144.321 +        if (cursor == len) {
 144.322 +            signum = 0;
 144.323 +            mag = ZERO.mag;
 144.324 +            return;
 144.325 +        }
 144.326 +
 144.327 +        numDigits = len - cursor;
 144.328 +        signum = sign;
 144.329 +
 144.330 +        // Pre-allocate array of expected size. May be too large but can
 144.331 +        // never be too small. Typically exact.
 144.332 +        int numBits = (int)(((numDigits * bitsPerDigit[radix]) >>> 10) + 1);
 144.333 +        int numWords = (numBits + 31) >>> 5;
 144.334 +        int[] magnitude = new int[numWords];
 144.335 +
 144.336 +        // Process first (potentially short) digit group
 144.337 +        int firstGroupLen = numDigits % digitsPerInt[radix];
 144.338 +        if (firstGroupLen == 0)
 144.339 +            firstGroupLen = digitsPerInt[radix];
 144.340 +        String group = val.substring(cursor, cursor += firstGroupLen);
 144.341 +        magnitude[numWords - 1] = Integer.parseInt(group, radix);
 144.342 +        if (magnitude[numWords - 1] < 0)
 144.343 +            throw new NumberFormatException("Illegal digit");
 144.344 +
 144.345 +        // Process remaining digit groups
 144.346 +        int superRadix = intRadix[radix];
 144.347 +        int groupVal = 0;
 144.348 +        while (cursor < len) {
 144.349 +            group = val.substring(cursor, cursor += digitsPerInt[radix]);
 144.350 +            groupVal = Integer.parseInt(group, radix);
 144.351 +            if (groupVal < 0)
 144.352 +                throw new NumberFormatException("Illegal digit");
 144.353 +            destructiveMulAdd(magnitude, superRadix, groupVal);
 144.354 +        }
 144.355 +        // Required for cases where the array was overallocated.
 144.356 +        mag = trustedStripLeadingZeroInts(magnitude);
 144.357 +    }
 144.358 +
 144.359 +    // Constructs a new BigInteger using a char array with radix=10
 144.360 +    BigInteger(char[] val) {
 144.361 +        int cursor = 0, numDigits;
 144.362 +        int len = val.length;
 144.363 +
 144.364 +        // Check for leading minus sign
 144.365 +        int sign = 1;
 144.366 +        if (val[0] == '-') {
 144.367 +            if (len == 1)
 144.368 +                throw new NumberFormatException("Zero length BigInteger");
 144.369 +            sign = -1;
 144.370 +            cursor = 1;
 144.371 +        } else if (val[0] == '+') {
 144.372 +            if (len == 1)
 144.373 +                throw new NumberFormatException("Zero length BigInteger");
 144.374 +            cursor = 1;
 144.375 +        }
 144.376 +
 144.377 +        // Skip leading zeros and compute number of digits in magnitude
 144.378 +        while (cursor < len && Character.digit(val[cursor], 10) == 0)
 144.379 +            cursor++;
 144.380 +        if (cursor == len) {
 144.381 +            signum = 0;
 144.382 +            mag = ZERO.mag;
 144.383 +            return;
 144.384 +        }
 144.385 +
 144.386 +        numDigits = len - cursor;
 144.387 +        signum = sign;
 144.388 +
 144.389 +        // Pre-allocate array of expected size
 144.390 +        int numWords;
 144.391 +        if (len < 10) {
 144.392 +            numWords = 1;
 144.393 +        } else {
 144.394 +            int numBits = (int)(((numDigits * bitsPerDigit[10]) >>> 10) + 1);
 144.395 +            numWords = (numBits + 31) >>> 5;
 144.396 +        }
 144.397 +        int[] magnitude = new int[numWords];
 144.398 +
 144.399 +        // Process first (potentially short) digit group
 144.400 +        int firstGroupLen = numDigits % digitsPerInt[10];
 144.401 +        if (firstGroupLen == 0)
 144.402 +            firstGroupLen = digitsPerInt[10];
 144.403 +        magnitude[numWords - 1] = parseInt(val, cursor,  cursor += firstGroupLen);
 144.404 +
 144.405 +        // Process remaining digit groups
 144.406 +        while (cursor < len) {
 144.407 +            int groupVal = parseInt(val, cursor, cursor += digitsPerInt[10]);
 144.408 +            destructiveMulAdd(magnitude, intRadix[10], groupVal);
 144.409 +        }
 144.410 +        mag = trustedStripLeadingZeroInts(magnitude);
 144.411 +    }
 144.412 +
 144.413 +    // Create an integer with the digits between the two indexes
 144.414 +    // Assumes start < end. The result may be negative, but it
 144.415 +    // is to be treated as an unsigned value.
 144.416 +    private int parseInt(char[] source, int start, int end) {
 144.417 +        int result = Character.digit(source[start++], 10);
 144.418 +        if (result == -1)
 144.419 +            throw new NumberFormatException(new String(source));
 144.420 +
 144.421 +        for (int index = start; index<end; index++) {
 144.422 +            int nextVal = Character.digit(source[index], 10);
 144.423 +            if (nextVal == -1)
 144.424 +                throw new NumberFormatException(new String(source));
 144.425 +            result = 10*result + nextVal;
 144.426 +        }
 144.427 +
 144.428 +        return result;
 144.429 +    }
 144.430 +
 144.431 +    // bitsPerDigit in the given radix times 1024
 144.432 +    // Rounded up to avoid underallocation.
 144.433 +    private static long bitsPerDigit[] = { 0, 0,
 144.434 +        1024, 1624, 2048, 2378, 2648, 2875, 3072, 3247, 3402, 3543, 3672,
 144.435 +        3790, 3899, 4001, 4096, 4186, 4271, 4350, 4426, 4498, 4567, 4633,
 144.436 +        4696, 4756, 4814, 4870, 4923, 4975, 5025, 5074, 5120, 5166, 5210,
 144.437 +                                           5253, 5295};
 144.438 +
 144.439 +    // Multiply x array times word y in place, and add word z
 144.440 +    private static void destructiveMulAdd(int[] x, int y, int z) {
 144.441 +        // Perform the multiplication word by word
 144.442 +        long ylong = y & LONG_MASK;
 144.443 +        long zlong = z & LONG_MASK;
 144.444 +        int len = x.length;
 144.445 +
 144.446 +        long product = 0;
 144.447 +        long carry = 0;
 144.448 +        for (int i = len-1; i >= 0; i--) {
 144.449 +            product = ylong * (x[i] & LONG_MASK) + carry;
 144.450 +            x[i] = (int)product;
 144.451 +            carry = product >>> 32;
 144.452 +        }
 144.453 +
 144.454 +        // Perform the addition
 144.455 +        long sum = (x[len-1] & LONG_MASK) + zlong;
 144.456 +        x[len-1] = (int)sum;
 144.457 +        carry = sum >>> 32;
 144.458 +        for (int i = len-2; i >= 0; i--) {
 144.459 +            sum = (x[i] & LONG_MASK) + carry;
 144.460 +            x[i] = (int)sum;
 144.461 +            carry = sum >>> 32;
 144.462 +        }
 144.463 +    }
 144.464 +
 144.465 +    /**
 144.466 +     * Translates the decimal String representation of a BigInteger into a
 144.467 +     * BigInteger.  The String representation consists of an optional minus
 144.468 +     * sign followed by a sequence of one or more decimal digits.  The
 144.469 +     * character-to-digit mapping is provided by {@code Character.digit}.
 144.470 +     * The String may not contain any extraneous characters (whitespace, for
 144.471 +     * example).
 144.472 +     *
 144.473 +     * @param val decimal String representation of BigInteger.
 144.474 +     * @throws NumberFormatException {@code val} is not a valid representation
 144.475 +     *         of a BigInteger.
 144.476 +     * @see    Character#digit
 144.477 +     */
 144.478 +    public BigInteger(String val) {
 144.479 +        this(val, 10);
 144.480 +    }
 144.481 +
 144.482 +    /**
 144.483 +     * Constructs a randomly generated BigInteger, uniformly distributed over
 144.484 +     * the range 0 to (2<sup>{@code numBits}</sup> - 1), inclusive.
 144.485 +     * The uniformity of the distribution assumes that a fair source of random
 144.486 +     * bits is provided in {@code rnd}.  Note that this constructor always
 144.487 +     * constructs a non-negative BigInteger.
 144.488 +     *
 144.489 +     * @param  numBits maximum bitLength of the new BigInteger.
 144.490 +     * @param  rnd source of randomness to be used in computing the new
 144.491 +     *         BigInteger.
 144.492 +     * @throws IllegalArgumentException {@code numBits} is negative.
 144.493 +     * @see #bitLength()
 144.494 +     */
 144.495 +    public BigInteger(int numBits, Random rnd) {
 144.496 +        this(1, randomBits(numBits, rnd));
 144.497 +    }
 144.498 +
 144.499 +    private static byte[] randomBits(int numBits, Random rnd) {
 144.500 +        if (numBits < 0)
 144.501 +            throw new IllegalArgumentException("numBits must be non-negative");
 144.502 +        int numBytes = (int)(((long)numBits+7)/8); // avoid overflow
 144.503 +        byte[] randomBits = new byte[numBytes];
 144.504 +
 144.505 +        // Generate random bytes and mask out any excess bits
 144.506 +        if (numBytes > 0) {
 144.507 +            rnd.nextBytes(randomBits);
 144.508 +            int excessBits = 8*numBytes - numBits;
 144.509 +            randomBits[0] &= (1 << (8-excessBits)) - 1;
 144.510 +        }
 144.511 +        return randomBits;
 144.512 +    }
 144.513 +
 144.514 +    /**
 144.515 +     * Constructs a randomly generated positive BigInteger that is probably
 144.516 +     * prime, with the specified bitLength.
 144.517 +     *
 144.518 +     * <p>It is recommended that the {@link #probablePrime probablePrime}
 144.519 +     * method be used in preference to this constructor unless there
 144.520 +     * is a compelling need to specify a certainty.
 144.521 +     *
 144.522 +     * @param  bitLength bitLength of the returned BigInteger.
 144.523 +     * @param  certainty a measure of the uncertainty that the caller is
 144.524 +     *         willing to tolerate.  The probability that the new BigInteger
 144.525 +     *         represents a prime number will exceed
 144.526 +     *         (1 - 1/2<sup>{@code certainty}</sup>).  The execution time of
 144.527 +     *         this constructor is proportional to the value of this parameter.
 144.528 +     * @param  rnd source of random bits used to select candidates to be
 144.529 +     *         tested for primality.
 144.530 +     * @throws ArithmeticException {@code bitLength < 2}.
 144.531 +     * @see    #bitLength()
 144.532 +     */
 144.533 +    public BigInteger(int bitLength, int certainty, Random rnd) {
 144.534 +        BigInteger prime;
 144.535 +
 144.536 +        if (bitLength < 2)
 144.537 +            throw new ArithmeticException("bitLength < 2");
 144.538 +        // The cutoff of 95 was chosen empirically for best performance
 144.539 +        prime = (bitLength < 95 ? smallPrime(bitLength, certainty, rnd)
 144.540 +                                : largePrime(bitLength, certainty, rnd));
 144.541 +        signum = 1;
 144.542 +        mag = prime.mag;
 144.543 +    }
 144.544 +
 144.545 +    // Minimum size in bits that the requested prime number has
 144.546 +    // before we use the large prime number generating algorithms
 144.547 +    private static final int SMALL_PRIME_THRESHOLD = 95;
 144.548 +
 144.549 +    // Certainty required to meet the spec of probablePrime
 144.550 +    private static final int DEFAULT_PRIME_CERTAINTY = 100;
 144.551 +
 144.552 +    /**
 144.553 +     * Returns a positive BigInteger that is probably prime, with the
 144.554 +     * specified bitLength. The probability that a BigInteger returned
 144.555 +     * by this method is composite does not exceed 2<sup>-100</sup>.
 144.556 +     *
 144.557 +     * @param  bitLength bitLength of the returned BigInteger.
 144.558 +     * @param  rnd source of random bits used to select candidates to be
 144.559 +     *         tested for primality.
 144.560 +     * @return a BigInteger of {@code bitLength} bits that is probably prime
 144.561 +     * @throws ArithmeticException {@code bitLength < 2}.
 144.562 +     * @see    #bitLength()
 144.563 +     * @since 1.4
 144.564 +     */
 144.565 +    public static BigInteger probablePrime(int bitLength, Random rnd) {
 144.566 +        if (bitLength < 2)
 144.567 +            throw new ArithmeticException("bitLength < 2");
 144.568 +
 144.569 +        // The cutoff of 95 was chosen empirically for best performance
 144.570 +        return (bitLength < SMALL_PRIME_THRESHOLD ?
 144.571 +                smallPrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd) :
 144.572 +                largePrime(bitLength, DEFAULT_PRIME_CERTAINTY, rnd));
 144.573 +    }
 144.574 +
 144.575 +    /**
 144.576 +     * Find a random number of the specified bitLength that is probably prime.
 144.577 +     * This method is used for smaller primes, its performance degrades on
 144.578 +     * larger bitlengths.
 144.579 +     *
 144.580 +     * This method assumes bitLength > 1.
 144.581 +     */
 144.582 +    private static BigInteger smallPrime(int bitLength, int certainty, Random rnd) {
 144.583 +        int magLen = (bitLength + 31) >>> 5;
 144.584 +        int temp[] = new int[magLen];
 144.585 +        int highBit = 1 << ((bitLength+31) & 0x1f);  // High bit of high int
 144.586 +        int highMask = (highBit << 1) - 1;  // Bits to keep in high int
 144.587 +
 144.588 +        while(true) {
 144.589 +            // Construct a candidate
 144.590 +            for (int i=0; i<magLen; i++)
 144.591 +                temp[i] = rnd.nextInt();
 144.592 +            temp[0] = (temp[0] & highMask) | highBit;  // Ensure exact length
 144.593 +            if (bitLength > 2)
 144.594 +                temp[magLen-1] |= 1;  // Make odd if bitlen > 2
 144.595 +
 144.596 +            BigInteger p = new BigInteger(temp, 1);
 144.597 +
 144.598 +            // Do cheap "pre-test" if applicable
 144.599 +            if (bitLength > 6) {
 144.600 +                long r = p.remainder(SMALL_PRIME_PRODUCT).longValue();
 144.601 +                if ((r%3==0)  || (r%5==0)  || (r%7==0)  || (r%11==0) ||
 144.602 +                    (r%13==0) || (r%17==0) || (r%19==0) || (r%23==0) ||
 144.603 +                    (r%29==0) || (r%31==0) || (r%37==0) || (r%41==0))
 144.604 +                    continue; // Candidate is composite; try another
 144.605 +            }
 144.606 +
 144.607 +            // All candidates of bitLength 2 and 3 are prime by this point
 144.608 +            if (bitLength < 4)
 144.609 +                return p;
 144.610 +
 144.611 +            // Do expensive test if we survive pre-test (or it's inapplicable)
 144.612 +            if (p.primeToCertainty(certainty, rnd))
 144.613 +                return p;
 144.614 +        }
 144.615 +    }
 144.616 +
 144.617 +    private static final BigInteger SMALL_PRIME_PRODUCT
 144.618 +                       = valueOf(3L*5*7*11*13*17*19*23*29*31*37*41);
 144.619 +
 144.620 +    /**
 144.621 +     * Find a random number of the specified bitLength that is probably prime.
 144.622 +     * This method is more appropriate for larger bitlengths since it uses
 144.623 +     * a sieve to eliminate most composites before using a more expensive
 144.624 +     * test.
 144.625 +     */
 144.626 +    private static BigInteger largePrime(int bitLength, int certainty, Random rnd) {
 144.627 +        BigInteger p;
 144.628 +        p = new BigInteger(bitLength, rnd).setBit(bitLength-1);
 144.629 +        p.mag[p.mag.length-1] &= 0xfffffffe;
 144.630 +
 144.631 +        // Use a sieve length likely to contain the next prime number
 144.632 +        int searchLen = (bitLength / 20) * 64;
 144.633 +        BitSieve searchSieve = new BitSieve(p, searchLen);
 144.634 +        BigInteger candidate = searchSieve.retrieve(p, certainty, rnd);
 144.635 +
 144.636 +        while ((candidate == null) || (candidate.bitLength() != bitLength)) {
 144.637 +            p = p.add(BigInteger.valueOf(2*searchLen));
 144.638 +            if (p.bitLength() != bitLength)
 144.639 +                p = new BigInteger(bitLength, rnd).setBit(bitLength-1);
 144.640 +            p.mag[p.mag.length-1] &= 0xfffffffe;
 144.641 +            searchSieve = new BitSieve(p, searchLen);
 144.642 +            candidate = searchSieve.retrieve(p, certainty, rnd);
 144.643 +        }
 144.644 +        return candidate;
 144.645 +    }
 144.646 +
 144.647 +   /**
 144.648 +    * Returns the first integer greater than this {@code BigInteger} that
 144.649 +    * is probably prime.  The probability that the number returned by this
 144.650 +    * method is composite does not exceed 2<sup>-100</sup>. This method will
 144.651 +    * never skip over a prime when searching: if it returns {@code p}, there
 144.652 +    * is no prime {@code q} such that {@code this < q < p}.
 144.653 +    *
 144.654 +    * @return the first integer greater than this {@code BigInteger} that
 144.655 +    *         is probably prime.
 144.656 +    * @throws ArithmeticException {@code this < 0}.
 144.657 +    * @since 1.5
 144.658 +    */
 144.659 +    public BigInteger nextProbablePrime() {
 144.660 +        if (this.signum < 0)
 144.661 +            throw new ArithmeticException("start < 0: " + this);
 144.662 +
 144.663 +        // Handle trivial cases
 144.664 +        if ((this.signum == 0) || this.equals(ONE))
 144.665 +            return TWO;
 144.666 +
 144.667 +        BigInteger result = this.add(ONE);
 144.668 +
 144.669 +        // Fastpath for small numbers
 144.670 +        if (result.bitLength() < SMALL_PRIME_THRESHOLD) {
 144.671 +
 144.672 +            // Ensure an odd number
 144.673 +            if (!result.testBit(0))
 144.674 +                result = result.add(ONE);
 144.675 +
 144.676 +            while(true) {
 144.677 +                // Do cheap "pre-test" if applicable
 144.678 +                if (result.bitLength() > 6) {
 144.679 +                    long r = result.remainder(SMALL_PRIME_PRODUCT).longValue();
 144.680 +                    if ((r%3==0)  || (r%5==0)  || (r%7==0)  || (r%11==0) ||
 144.681 +                        (r%13==0) || (r%17==0) || (r%19==0) || (r%23==0) ||
 144.682 +                        (r%29==0) || (r%31==0) || (r%37==0) || (r%41==0)) {
 144.683 +                        result = result.add(TWO);
 144.684 +                        continue; // Candidate is composite; try another
 144.685 +                    }
 144.686 +                }
 144.687 +
 144.688 +                // All candidates of bitLength 2 and 3 are prime by this point
 144.689 +                if (result.bitLength() < 4)
 144.690 +                    return result;
 144.691 +
 144.692 +                // The expensive test
 144.693 +                if (result.primeToCertainty(DEFAULT_PRIME_CERTAINTY, null))
 144.694 +                    return result;
 144.695 +
 144.696 +                result = result.add(TWO);
 144.697 +            }
 144.698 +        }
 144.699 +
 144.700 +        // Start at previous even number
 144.701 +        if (result.testBit(0))
 144.702 +            result = result.subtract(ONE);
 144.703 +
 144.704 +        // Looking for the next large prime
 144.705 +        int searchLen = (result.bitLength() / 20) * 64;
 144.706 +
 144.707 +        while(true) {
 144.708 +           BitSieve searchSieve = new BitSieve(result, searchLen);
 144.709 +           BigInteger candidate = searchSieve.retrieve(result,
 144.710 +                                                 DEFAULT_PRIME_CERTAINTY, null);
 144.711 +           if (candidate != null)
 144.712 +               return candidate;
 144.713 +           result = result.add(BigInteger.valueOf(2 * searchLen));
 144.714 +        }
 144.715 +    }
 144.716 +
 144.717 +    /**
 144.718 +     * Returns {@code true} if this BigInteger is probably prime,
 144.719 +     * {@code false} if it's definitely composite.
 144.720 +     *
 144.721 +     * This method assumes bitLength > 2.
 144.722 +     *
 144.723 +     * @param  certainty a measure of the uncertainty that the caller is
 144.724 +     *         willing to tolerate: if the call returns {@code true}
 144.725 +     *         the probability that this BigInteger is prime exceeds
 144.726 +     *         {@code (1 - 1/2<sup>certainty</sup>)}.  The execution time of
 144.727 +     *         this method is proportional to the value of this parameter.
 144.728 +     * @return {@code true} if this BigInteger is probably prime,
 144.729 +     *         {@code false} if it's definitely composite.
 144.730 +     */
 144.731 +    boolean primeToCertainty(int certainty, Random random) {
 144.732 +        int rounds = 0;
 144.733 +        int n = (Math.min(certainty, Integer.MAX_VALUE-1)+1)/2;
 144.734 +
 144.735 +        // The relationship between the certainty and the number of rounds
 144.736 +        // we perform is given in the draft standard ANSI X9.80, "PRIME
 144.737 +        // NUMBER GENERATION, PRIMALITY TESTING, AND PRIMALITY CERTIFICATES".
 144.738 +        int sizeInBits = this.bitLength();
 144.739 +        if (sizeInBits < 100) {
 144.740 +            rounds = 50;
 144.741 +            rounds = n < rounds ? n : rounds;
 144.742 +            return passesMillerRabin(rounds, random);
 144.743 +        }
 144.744 +
 144.745 +        if (sizeInBits < 256) {
 144.746 +            rounds = 27;
 144.747 +        } else if (sizeInBits < 512) {
 144.748 +            rounds = 15;
 144.749 +        } else if (sizeInBits < 768) {
 144.750 +            rounds = 8;
 144.751 +        } else if (sizeInBits < 1024) {
 144.752 +            rounds = 4;
 144.753 +        } else {
 144.754 +            rounds = 2;
 144.755 +        }
 144.756 +        rounds = n < rounds ? n : rounds;
 144.757 +
 144.758 +        return passesMillerRabin(rounds, random) && passesLucasLehmer();
 144.759 +    }
 144.760 +
 144.761 +    /**
 144.762 +     * Returns true iff this BigInteger is a Lucas-Lehmer probable prime.
 144.763 +     *
 144.764 +     * The following assumptions are made:
 144.765 +     * This BigInteger is a positive, odd number.
 144.766 +     */
 144.767 +    private boolean passesLucasLehmer() {
 144.768 +        BigInteger thisPlusOne = this.add(ONE);
 144.769 +
 144.770 +        // Step 1
 144.771 +        int d = 5;
 144.772 +        while (jacobiSymbol(d, this) != -1) {
 144.773 +            // 5, -7, 9, -11, ...
 144.774 +            d = (d<0) ? Math.abs(d)+2 : -(d+2);
 144.775 +        }
 144.776 +
 144.777 +        // Step 2
 144.778 +        BigInteger u = lucasLehmerSequence(d, thisPlusOne, this);
 144.779 +
 144.780 +        // Step 3
 144.781 +        return u.mod(this).equals(ZERO);
 144.782 +    }
 144.783 +
 144.784 +    /**
 144.785 +     * Computes Jacobi(p,n).
 144.786 +     * Assumes n positive, odd, n>=3.
 144.787 +     */
 144.788 +    private static int jacobiSymbol(int p, BigInteger n) {
 144.789 +        if (p == 0)
 144.790 +            return 0;
 144.791 +
 144.792 +        // Algorithm and comments adapted from Colin Plumb's C library.
 144.793 +        int j = 1;
 144.794 +        int u = n.mag[n.mag.length-1];
 144.795 +
 144.796 +        // Make p positive
 144.797 +        if (p < 0) {
 144.798 +            p = -p;
 144.799 +            int n8 = u & 7;
 144.800 +            if ((n8 == 3) || (n8 == 7))
 144.801 +                j = -j; // 3 (011) or 7 (111) mod 8
 144.802 +        }
 144.803 +
 144.804 +        // Get rid of factors of 2 in p
 144.805 +        while ((p & 3) == 0)
 144.806 +            p >>= 2;
 144.807 +        if ((p & 1) == 0) {
 144.808 +            p >>= 1;
 144.809 +            if (((u ^ (u>>1)) & 2) != 0)
 144.810 +                j = -j; // 3 (011) or 5 (101) mod 8
 144.811 +        }
 144.812 +        if (p == 1)
 144.813 +            return j;
 144.814 +        // Then, apply quadratic reciprocity
 144.815 +        if ((p & u & 2) != 0)   // p = u = 3 (mod 4)?
 144.816 +            j = -j;
 144.817 +        // And reduce u mod p
 144.818 +        u = n.mod(BigInteger.valueOf(p)).intValue();
 144.819 +
 144.820 +        // Now compute Jacobi(u,p), u < p
 144.821 +        while (u != 0) {
 144.822 +            while ((u & 3) == 0)
 144.823 +                u >>= 2;
 144.824 +            if ((u & 1) == 0) {
 144.825 +                u >>= 1;
 144.826 +                if (((p ^ (p>>1)) & 2) != 0)
 144.827 +                    j = -j;     // 3 (011) or 5 (101) mod 8
 144.828 +            }
 144.829 +            if (u == 1)
 144.830 +                return j;
 144.831 +            // Now both u and p are odd, so use quadratic reciprocity
 144.832 +            assert (u < p);
 144.833 +            int t = u; u = p; p = t;
 144.834 +            if ((u & p & 2) != 0) // u = p = 3 (mod 4)?
 144.835 +                j = -j;
 144.836 +            // Now u >= p, so it can be reduced
 144.837 +            u %= p;
 144.838 +        }
 144.839 +        return 0;
 144.840 +    }
 144.841 +
 144.842 +    private static BigInteger lucasLehmerSequence(int z, BigInteger k, BigInteger n) {
 144.843 +        BigInteger d = BigInteger.valueOf(z);
 144.844 +        BigInteger u = ONE; BigInteger u2;
 144.845 +        BigInteger v = ONE; BigInteger v2;
 144.846 +
 144.847 +        for (int i=k.bitLength()-2; i>=0; i--) {
 144.848 +            u2 = u.multiply(v).mod(n);
 144.849 +
 144.850 +            v2 = v.square().add(d.multiply(u.square())).mod(n);
 144.851 +            if (v2.testBit(0))
 144.852 +                v2 = v2.subtract(n);
 144.853 +
 144.854 +            v2 = v2.shiftRight(1);
 144.855 +
 144.856 +            u = u2; v = v2;
 144.857 +            if (k.testBit(i)) {
 144.858 +                u2 = u.add(v).mod(n);
 144.859 +                if (u2.testBit(0))
 144.860 +                    u2 = u2.subtract(n);
 144.861 +
 144.862 +                u2 = u2.shiftRight(1);
 144.863 +                v2 = v.add(d.multiply(u)).mod(n);
 144.864 +                if (v2.testBit(0))
 144.865 +                    v2 = v2.subtract(n);
 144.866 +                v2 = v2.shiftRight(1);
 144.867 +
 144.868 +                u = u2; v = v2;
 144.869 +            }
 144.870 +        }
 144.871 +        return u;
 144.872 +    }
 144.873 +
 144.874 +    private static volatile Random staticRandom;
 144.875 +
 144.876 +    private static Random getSecureRandom() {
 144.877 +        if (staticRandom == null) {
 144.878 +            staticRandom = new Random();
 144.879 +        }
 144.880 +        return staticRandom;
 144.881 +    }
 144.882 +
 144.883 +    /**
 144.884 +     * Returns true iff this BigInteger passes the specified number of
 144.885 +     * Miller-Rabin tests. This test is taken from the DSA spec (NIST FIPS
 144.886 +     * 186-2).
 144.887 +     *
 144.888 +     * The following assumptions are made:
 144.889 +     * This BigInteger is a positive, odd number greater than 2.
 144.890 +     * iterations<=50.
 144.891 +     */
 144.892 +    private boolean passesMillerRabin(int iterations, Random rnd) {
 144.893 +        // Find a and m such that m is odd and this == 1 + 2**a * m
 144.894 +        BigInteger thisMinusOne = this.subtract(ONE);
 144.895 +        BigInteger m = thisMinusOne;
 144.896 +        int a = m.getLowestSetBit();
 144.897 +        m = m.shiftRight(a);
 144.898 +
 144.899 +        // Do the tests
 144.900 +        if (rnd == null) {
 144.901 +            rnd = getSecureRandom();
 144.902 +        }
 144.903 +        for (int i=0; i<iterations; i++) {
 144.904 +            // Generate a uniform random on (1, this)
 144.905 +            BigInteger b;
 144.906 +            do {
 144.907 +                b = new BigInteger(this.bitLength(), rnd);
 144.908 +            } while (b.compareTo(ONE) <= 0 || b.compareTo(this) >= 0);
 144.909 +
 144.910 +            int j = 0;
 144.911 +            BigInteger z = b.modPow(m, this);
 144.912 +            while(!((j==0 && z.equals(ONE)) || z.equals(thisMinusOne))) {
 144.913 +                if (j>0 && z.equals(ONE) || ++j==a)
 144.914 +                    return false;
 144.915 +                z = z.modPow(TWO, this);
 144.916 +            }
 144.917 +        }
 144.918 +        return true;
 144.919 +    }
 144.920 +
 144.921 +    /**
 144.922 +     * This internal constructor differs from its public cousin
 144.923 +     * with the arguments reversed in two ways: it assumes that its
 144.924 +     * arguments are correct, and it doesn't copy the magnitude array.
 144.925 +     */
 144.926 +    BigInteger(int[] magnitude, int signum) {
 144.927 +        this.signum = (magnitude.length==0 ? 0 : signum);
 144.928 +        this.mag = magnitude;
 144.929 +    }
 144.930 +
 144.931 +    /**
 144.932 +     * This private constructor is for internal use and assumes that its
 144.933 +     * arguments are correct.
 144.934 +     */
 144.935 +    private BigInteger(byte[] magnitude, int signum) {
 144.936 +        this.signum = (magnitude.length==0 ? 0 : signum);
 144.937 +        this.mag = stripLeadingZeroBytes(magnitude);
 144.938 +    }
 144.939 +
 144.940 +    //Static Factory Methods
 144.941 +
 144.942 +    /**
 144.943 +     * Returns a BigInteger whose value is equal to that of the
 144.944 +     * specified {@code long}.  This "static factory method" is
 144.945 +     * provided in preference to a ({@code long}) constructor
 144.946 +     * because it allows for reuse of frequently used BigIntegers.
 144.947 +     *
 144.948 +     * @param  val value of the BigInteger to return.
 144.949 +     * @return a BigInteger with the specified value.
 144.950 +     */
 144.951 +    public static BigInteger valueOf(long val) {
 144.952 +        // If -MAX_CONSTANT < val < MAX_CONSTANT, return stashed constant
 144.953 +        if (val == 0)
 144.954 +            return ZERO;
 144.955 +        if (val > 0 && val <= MAX_CONSTANT)
 144.956 +            return posConst[(int) val];
 144.957 +        else if (val < 0 && val >= -MAX_CONSTANT)
 144.958 +            return negConst[(int) -val];
 144.959 +
 144.960 +        return new BigInteger(val);
 144.961 +    }
 144.962 +
 144.963 +    /**
 144.964 +     * Constructs a BigInteger with the specified value, which may not be zero.
 144.965 +     */
 144.966 +    private BigInteger(long val) {
 144.967 +        if (val < 0) {
 144.968 +            val = -val;
 144.969 +            signum = -1;
 144.970 +        } else {
 144.971 +            signum = 1;
 144.972 +        }
 144.973 +
 144.974 +        int highWord = (int)(val >>> 32);
 144.975 +        if (highWord==0) {
 144.976 +            mag = new int[1];
 144.977 +            mag[0] = (int)val;
 144.978 +        } else {
 144.979 +            mag = new int[2];
 144.980 +            mag[0] = highWord;
 144.981 +            mag[1] = (int)val;
 144.982 +        }
 144.983 +    }
 144.984 +
 144.985 +    /**
 144.986 +     * Returns a BigInteger with the given two's complement representation.
 144.987 +     * Assumes that the input array will not be modified (the returned
 144.988 +     * BigInteger will reference the input array if feasible).
 144.989 +     */
 144.990 +    private static BigInteger valueOf(int val[]) {
 144.991 +        return (val[0]>0 ? new BigInteger(val, 1) : new BigInteger(val));
 144.992 +    }
 144.993 +
 144.994 +    // Constants
 144.995 +
 144.996 +    /**
 144.997 +     * Initialize static constant array when class is loaded.
 144.998 +     */
 144.999 +    private final static int MAX_CONSTANT = 16;
144.1000 +    private static BigInteger posConst[] = new BigInteger[MAX_CONSTANT+1];
144.1001 +    private static BigInteger negConst[] = new BigInteger[MAX_CONSTANT+1];
144.1002 +    static {
144.1003 +        for (int i = 1; i <= MAX_CONSTANT; i++) {
144.1004 +            int[] magnitude = new int[1];
144.1005 +            magnitude[0] = i;
144.1006 +            posConst[i] = new BigInteger(magnitude,  1);
144.1007 +            negConst[i] = new BigInteger(magnitude, -1);
144.1008 +        }
144.1009 +    }
144.1010 +
144.1011 +    /**
144.1012 +     * The BigInteger constant zero.
144.1013 +     *
144.1014 +     * @since   1.2
144.1015 +     */
144.1016 +    public static final BigInteger ZERO = new BigInteger(new int[0], 0);
144.1017 +
144.1018 +    /**
144.1019 +     * The BigInteger constant one.
144.1020 +     *
144.1021 +     * @since   1.2
144.1022 +     */
144.1023 +    public static final BigInteger ONE = valueOf(1);
144.1024 +
144.1025 +    /**
144.1026 +     * The BigInteger constant two.  (Not exported.)
144.1027 +     */
144.1028 +    private static final BigInteger TWO = valueOf(2);
144.1029 +
144.1030 +    /**
144.1031 +     * The BigInteger constant ten.
144.1032 +     *
144.1033 +     * @since   1.5
144.1034 +     */
144.1035 +    public static final BigInteger TEN = valueOf(10);
144.1036 +
144.1037 +    // Arithmetic Operations
144.1038 +
144.1039 +    /**
144.1040 +     * Returns a BigInteger whose value is {@code (this + val)}.
144.1041 +     *
144.1042 +     * @param  val value to be added to this BigInteger.
144.1043 +     * @return {@code this + val}
144.1044 +     */
144.1045 +    public BigInteger add(BigInteger val) {
144.1046 +        if (val.signum == 0)
144.1047 +            return this;
144.1048 +        if (signum == 0)
144.1049 +            return val;
144.1050 +        if (val.signum == signum)
144.1051 +            return new BigInteger(add(mag, val.mag), signum);
144.1052 +
144.1053 +        int cmp = compareMagnitude(val);
144.1054 +        if (cmp == 0)
144.1055 +            return ZERO;
144.1056 +        int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
144.1057 +                           : subtract(val.mag, mag));
144.1058 +        resultMag = trustedStripLeadingZeroInts(resultMag);
144.1059 +
144.1060 +        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
144.1061 +    }
144.1062 +
144.1063 +    /**
144.1064 +     * Adds the contents of the int arrays x and y. This method allocates
144.1065 +     * a new int array to hold the answer and returns a reference to that
144.1066 +     * array.
144.1067 +     */
144.1068 +    private static int[] add(int[] x, int[] y) {
144.1069 +        // If x is shorter, swap the two arrays
144.1070 +        if (x.length < y.length) {
144.1071 +            int[] tmp = x;
144.1072 +            x = y;
144.1073 +            y = tmp;
144.1074 +        }
144.1075 +
144.1076 +        int xIndex = x.length;
144.1077 +        int yIndex = y.length;
144.1078 +        int result[] = new int[xIndex];
144.1079 +        long sum = 0;
144.1080 +
144.1081 +        // Add common parts of both numbers
144.1082 +        while(yIndex > 0) {
144.1083 +            sum = (x[--xIndex] & LONG_MASK) +
144.1084 +                  (y[--yIndex] & LONG_MASK) + (sum >>> 32);
144.1085 +            result[xIndex] = (int)sum;
144.1086 +        }
144.1087 +
144.1088 +        // Copy remainder of longer number while carry propagation is required
144.1089 +        boolean carry = (sum >>> 32 != 0);
144.1090 +        while (xIndex > 0 && carry)
144.1091 +            carry = ((result[--xIndex] = x[xIndex] + 1) == 0);
144.1092 +
144.1093 +        // Copy remainder of longer number
144.1094 +        while (xIndex > 0)
144.1095 +            result[--xIndex] = x[xIndex];
144.1096 +
144.1097 +        // Grow result if necessary
144.1098 +        if (carry) {
144.1099 +            int bigger[] = new int[result.length + 1];
144.1100 +            System.arraycopy(result, 0, bigger, 1, result.length);
144.1101 +            bigger[0] = 0x01;
144.1102 +            return bigger;
144.1103 +        }
144.1104 +        return result;
144.1105 +    }
144.1106 +
144.1107 +    /**
144.1108 +     * Returns a BigInteger whose value is {@code (this - val)}.
144.1109 +     *
144.1110 +     * @param  val value to be subtracted from this BigInteger.
144.1111 +     * @return {@code this - val}
144.1112 +     */
144.1113 +    public BigInteger subtract(BigInteger val) {
144.1114 +        if (val.signum == 0)
144.1115 +            return this;
144.1116 +        if (signum == 0)
144.1117 +            return val.negate();
144.1118 +        if (val.signum != signum)
144.1119 +            return new BigInteger(add(mag, val.mag), signum);
144.1120 +
144.1121 +        int cmp = compareMagnitude(val);
144.1122 +        if (cmp == 0)
144.1123 +            return ZERO;
144.1124 +        int[] resultMag = (cmp > 0 ? subtract(mag, val.mag)
144.1125 +                           : subtract(val.mag, mag));
144.1126 +        resultMag = trustedStripLeadingZeroInts(resultMag);
144.1127 +        return new BigInteger(resultMag, cmp == signum ? 1 : -1);
144.1128 +    }
144.1129 +
144.1130 +    /**
144.1131 +     * Subtracts the contents of the second int arrays (little) from the
144.1132 +     * first (big).  The first int array (big) must represent a larger number
144.1133 +     * than the second.  This method allocates the space necessary to hold the
144.1134 +     * answer.
144.1135 +     */
144.1136 +    private static int[] subtract(int[] big, int[] little) {
144.1137 +        int bigIndex = big.length;
144.1138 +        int result[] = new int[bigIndex];
144.1139 +        int littleIndex = little.length;
144.1140 +        long difference = 0;
144.1141 +
144.1142 +        // Subtract common parts of both numbers
144.1143 +        while(littleIndex > 0) {
144.1144 +            difference = (big[--bigIndex] & LONG_MASK) -
144.1145 +                         (little[--littleIndex] & LONG_MASK) +
144.1146 +                         (difference >> 32);
144.1147 +            result[bigIndex] = (int)difference;
144.1148 +        }
144.1149 +
144.1150 +        // Subtract remainder of longer number while borrow propagates
144.1151 +        boolean borrow = (difference >> 32 != 0);
144.1152 +        while (bigIndex > 0 && borrow)
144.1153 +            borrow = ((result[--bigIndex] = big[bigIndex] - 1) == -1);
144.1154 +
144.1155 +        // Copy remainder of longer number
144.1156 +        while (bigIndex > 0)
144.1157 +            result[--bigIndex] = big[bigIndex];
144.1158 +
144.1159 +        return result;
144.1160 +    }
144.1161 +
144.1162 +    /**
144.1163 +     * Returns a BigInteger whose value is {@code (this * val)}.
144.1164 +     *
144.1165 +     * @param  val value to be multiplied by this BigInteger.
144.1166 +     * @return {@code this * val}
144.1167 +     */
144.1168 +    public BigInteger multiply(BigInteger val) {
144.1169 +        if (val.signum == 0 || signum == 0)
144.1170 +            return ZERO;
144.1171 +
144.1172 +        int[] result = multiplyToLen(mag, mag.length,
144.1173 +                                     val.mag, val.mag.length, null);
144.1174 +        result = trustedStripLeadingZeroInts(result);
144.1175 +        return new BigInteger(result, signum == val.signum ? 1 : -1);
144.1176 +    }
144.1177 +
144.1178 +    /**
144.1179 +     * Package private methods used by BigDecimal code to multiply a BigInteger
144.1180 +     * with a long. Assumes v is not equal to INFLATED.
144.1181 +     */
144.1182 +    BigInteger multiply(long v) {
144.1183 +        if (v == 0 || signum == 0)
144.1184 +          return ZERO;
144.1185 +        if (v == BigDecimal.INFLATED)
144.1186 +            return multiply(BigInteger.valueOf(v));
144.1187 +        int rsign = (v > 0 ? signum : -signum);
144.1188 +        if (v < 0)
144.1189 +            v = -v;
144.1190 +        long dh = v >>> 32;      // higher order bits
144.1191 +        long dl = v & LONG_MASK; // lower order bits
144.1192 +
144.1193 +        int xlen = mag.length;
144.1194 +        int[] value = mag;
144.1195 +        int[] rmag = (dh == 0L) ? (new int[xlen + 1]) : (new int[xlen + 2]);
144.1196 +        long carry = 0;
144.1197 +        int rstart = rmag.length - 1;
144.1198 +        for (int i = xlen - 1; i >= 0; i--) {
144.1199 +            long product = (value[i] & LONG_MASK) * dl + carry;
144.1200 +            rmag[rstart--] = (int)product;
144.1201 +            carry = product >>> 32;
144.1202 +        }
144.1203 +        rmag[rstart] = (int)carry;
144.1204 +        if (dh != 0L) {
144.1205 +            carry = 0;
144.1206 +            rstart = rmag.length - 2;
144.1207 +            for (int i = xlen - 1; i >= 0; i--) {
144.1208 +                long product = (value[i] & LONG_MASK) * dh +
144.1209 +                    (rmag[rstart] & LONG_MASK) + carry;
144.1210 +                rmag[rstart--] = (int)product;
144.1211 +                carry = product >>> 32;
144.1212 +            }
144.1213 +            rmag[0] = (int)carry;
144.1214 +        }
144.1215 +        if (carry == 0L)
144.1216 +            rmag = java.util.Arrays.copyOfRange(rmag, 1, rmag.length);
144.1217 +        return new BigInteger(rmag, rsign);
144.1218 +    }
144.1219 +
144.1220 +    /**
144.1221 +     * Multiplies int arrays x and y to the specified lengths and places
144.1222 +     * the result into z. There will be no leading zeros in the resultant array.
144.1223 +     */
144.1224 +    private int[] multiplyToLen(int[] x, int xlen, int[] y, int ylen, int[] z) {
144.1225 +        int xstart = xlen - 1;
144.1226 +        int ystart = ylen - 1;
144.1227 +
144.1228 +        if (z == null || z.length < (xlen+ ylen))
144.1229 +            z = new int[xlen+ylen];
144.1230 +
144.1231 +        long carry = 0;
144.1232 +        for (int j=ystart, k=ystart+1+xstart; j>=0; j--, k--) {
144.1233 +            long product = (y[j] & LONG_MASK) *
144.1234 +                           (x[xstart] & LONG_MASK) + carry;
144.1235 +            z[k] = (int)product;
144.1236 +            carry = product >>> 32;
144.1237 +        }
144.1238 +        z[xstart] = (int)carry;
144.1239 +
144.1240 +        for (int i = xstart-1; i >= 0; i--) {
144.1241 +            carry = 0;
144.1242 +            for (int j=ystart, k=ystart+1+i; j>=0; j--, k--) {
144.1243 +                long product = (y[j] & LONG_MASK) *
144.1244 +                               (x[i] & LONG_MASK) +
144.1245 +                               (z[k] & LONG_MASK) + carry;
144.1246 +                z[k] = (int)product;
144.1247 +                carry = product >>> 32;
144.1248 +            }
144.1249 +            z[i] = (int)carry;
144.1250 +        }
144.1251 +        return z;
144.1252 +    }
144.1253 +
144.1254 +    /**
144.1255 +     * Returns a BigInteger whose value is {@code (this<sup>2</sup>)}.
144.1256 +     *
144.1257 +     * @return {@code this<sup>2</sup>}
144.1258 +     */
144.1259 +    private BigInteger square() {
144.1260 +        if (signum == 0)
144.1261 +            return ZERO;
144.1262 +        int[] z = squareToLen(mag, mag.length, null);
144.1263 +        return new BigInteger(trustedStripLeadingZeroInts(z), 1);
144.1264 +    }
144.1265 +
144.1266 +    /**
144.1267 +     * Squares the contents of the int array x. The result is placed into the
144.1268 +     * int array z.  The contents of x are not changed.
144.1269 +     */
144.1270 +    private static final int[] squareToLen(int[] x, int len, int[] z) {
144.1271 +        /*
144.1272 +         * The algorithm used here is adapted from Colin Plumb's C library.
144.1273 +         * Technique: Consider the partial products in the multiplication
144.1274 +         * of "abcde" by itself:
144.1275 +         *
144.1276 +         *               a  b  c  d  e
144.1277 +         *            *  a  b  c  d  e
144.1278 +         *          ==================
144.1279 +         *              ae be ce de ee
144.1280 +         *           ad bd cd dd de
144.1281 +         *        ac bc cc cd ce
144.1282 +         *     ab bb bc bd be
144.1283 +         *  aa ab ac ad ae
144.1284 +         *
144.1285 +         * Note that everything above the main diagonal:
144.1286 +         *              ae be ce de = (abcd) * e
144.1287 +         *           ad bd cd       = (abc) * d
144.1288 +         *        ac bc             = (ab) * c
144.1289 +         *     ab                   = (a) * b
144.1290 +         *
144.1291 +         * is a copy of everything below the main diagonal:
144.1292 +         *                       de
144.1293 +         *                 cd ce
144.1294 +         *           bc bd be
144.1295 +         *     ab ac ad ae
144.1296 +         *
144.1297 +         * Thus, the sum is 2 * (off the diagonal) + diagonal.
144.1298 +         *
144.1299 +         * This is accumulated beginning with the diagonal (which
144.1300 +         * consist of the squares of the digits of the input), which is then
144.1301 +         * divided by two, the off-diagonal added, and multiplied by two
144.1302 +         * again.  The low bit is simply a copy of the low bit of the
144.1303 +         * input, so it doesn't need special care.
144.1304 +         */
144.1305 +        int zlen = len << 1;
144.1306 +        if (z == null || z.length < zlen)
144.1307 +            z = new int[zlen];
144.1308 +
144.1309 +        // Store the squares, right shifted one bit (i.e., divided by 2)
144.1310 +        int lastProductLowWord = 0;
144.1311 +        for (int j=0, i=0; j<len; j++) {
144.1312 +            long piece = (x[j] & LONG_MASK);
144.1313 +            long product = piece * piece;
144.1314 +            z[i++] = (lastProductLowWord << 31) | (int)(product >>> 33);
144.1315 +            z[i++] = (int)(product >>> 1);
144.1316 +            lastProductLowWord = (int)product;
144.1317 +        }
144.1318 +
144.1319 +        // Add in off-diagonal sums
144.1320 +        for (int i=len, offset=1; i>0; i--, offset+=2) {
144.1321 +            int t = x[i-1];
144.1322 +            t = mulAdd(z, x, offset, i-1, t);
144.1323 +            addOne(z, offset-1, i, t);
144.1324 +        }
144.1325 +
144.1326 +        // Shift back up and set low bit
144.1327 +        primitiveLeftShift(z, zlen, 1);
144.1328 +        z[zlen-1] |= x[len-1] & 1;
144.1329 +
144.1330 +        return z;
144.1331 +    }
144.1332 +
144.1333 +    /**
144.1334 +     * Returns a BigInteger whose value is {@code (this / val)}.
144.1335 +     *
144.1336 +     * @param  val value by which this BigInteger is to be divided.
144.1337 +     * @return {@code this / val}
144.1338 +     * @throws ArithmeticException if {@code val} is zero.
144.1339 +     */
144.1340 +    public BigInteger divide(BigInteger val) {
144.1341 +        MutableBigInteger q = new MutableBigInteger(),
144.1342 +                          a = new MutableBigInteger(this.mag),
144.1343 +                          b = new MutableBigInteger(val.mag);
144.1344 +
144.1345 +        a.divide(b, q);
144.1346 +        return q.toBigInteger(this.signum == val.signum ? 1 : -1);
144.1347 +    }
144.1348 +
144.1349 +    /**
144.1350 +     * Returns an array of two BigIntegers containing {@code (this / val)}
144.1351 +     * followed by {@code (this % val)}.
144.1352 +     *
144.1353 +     * @param  val value by which this BigInteger is to be divided, and the
144.1354 +     *         remainder computed.
144.1355 +     * @return an array of two BigIntegers: the quotient {@code (this / val)}
144.1356 +     *         is the initial element, and the remainder {@code (this % val)}
144.1357 +     *         is the final element.
144.1358 +     * @throws ArithmeticException if {@code val} is zero.
144.1359 +     */
144.1360 +    public BigInteger[] divideAndRemainder(BigInteger val) {
144.1361 +        BigInteger[] result = new BigInteger[2];
144.1362 +        MutableBigInteger q = new MutableBigInteger(),
144.1363 +                          a = new MutableBigInteger(this.mag),
144.1364 +                          b = new MutableBigInteger(val.mag);
144.1365 +        MutableBigInteger r = a.divide(b, q);
144.1366 +        result[0] = q.toBigInteger(this.signum == val.signum ? 1 : -1);
144.1367 +        result[1] = r.toBigInteger(this.signum);
144.1368 +        return result;
144.1369 +    }
144.1370 +
144.1371 +    /**
144.1372 +     * Returns a BigInteger whose value is {@code (this % val)}.
144.1373 +     *
144.1374 +     * @param  val value by which this BigInteger is to be divided, and the
144.1375 +     *         remainder computed.
144.1376 +     * @return {@code this % val}
144.1377 +     * @throws ArithmeticException if {@code val} is zero.
144.1378 +     */
144.1379 +    public BigInteger remainder(BigInteger val) {
144.1380 +        MutableBigInteger q = new MutableBigInteger(),
144.1381 +                          a = new MutableBigInteger(this.mag),
144.1382 +                          b = new MutableBigInteger(val.mag);
144.1383 +
144.1384 +        return a.divide(b, q).toBigInteger(this.signum);
144.1385 +    }
144.1386 +
144.1387 +    /**
144.1388 +     * Returns a BigInteger whose value is <tt>(this<sup>exponent</sup>)</tt>.
144.1389 +     * Note that {@code exponent} is an integer rather than a BigInteger.
144.1390 +     *
144.1391 +     * @param  exponent exponent to which this BigInteger is to be raised.
144.1392 +     * @return <tt>this<sup>exponent</sup></tt>
144.1393 +     * @throws ArithmeticException {@code exponent} is negative.  (This would
144.1394 +     *         cause the operation to yield a non-integer value.)
144.1395 +     */
144.1396 +    public BigInteger pow(int exponent) {
144.1397 +        if (exponent < 0)
144.1398 +            throw new ArithmeticException("Negative exponent");
144.1399 +        if (signum==0)
144.1400 +            return (exponent==0 ? ONE : this);
144.1401 +
144.1402 +        // Perform exponentiation using repeated squaring trick
144.1403 +        int newSign = (signum<0 && (exponent&1)==1 ? -1 : 1);
144.1404 +        int[] baseToPow2 = this.mag;
144.1405 +        int[] result = {1};
144.1406 +
144.1407 +        while (exponent != 0) {
144.1408 +            if ((exponent & 1)==1) {
144.1409 +                result = multiplyToLen(result, result.length,
144.1410 +                                       baseToPow2, baseToPow2.length, null);
144.1411 +                result = trustedStripLeadingZeroInts(result);
144.1412 +            }
144.1413 +            if ((exponent >>>= 1) != 0) {
144.1414 +                baseToPow2 = squareToLen(baseToPow2, baseToPow2.length, null);
144.1415 +                baseToPow2 = trustedStripLeadingZeroInts(baseToPow2);
144.1416 +            }
144.1417 +        }
144.1418 +        return new BigInteger(result, newSign);
144.1419 +    }
144.1420 +
144.1421 +    /**
144.1422 +     * Returns a BigInteger whose value is the greatest common divisor of
144.1423 +     * {@code abs(this)} and {@code abs(val)}.  Returns 0 if
144.1424 +     * {@code this==0 && val==0}.
144.1425 +     *
144.1426 +     * @param  val value with which the GCD is to be computed.
144.1427 +     * @return {@code GCD(abs(this), abs(val))}
144.1428 +     */
144.1429 +    public BigInteger gcd(BigInteger val) {
144.1430 +        if (val.signum == 0)
144.1431 +            return this.abs();
144.1432 +        else if (this.signum == 0)
144.1433 +            return val.abs();
144.1434 +
144.1435 +        MutableBigInteger a = new MutableBigInteger(this);
144.1436 +        MutableBigInteger b = new MutableBigInteger(val);
144.1437 +
144.1438 +        MutableBigInteger result = a.hybridGCD(b);
144.1439 +
144.1440 +        return result.toBigInteger(1);
144.1441 +    }
144.1442 +
144.1443 +    /**
144.1444 +     * Package private method to return bit length for an integer.
144.1445 +     */
144.1446 +    static int bitLengthForInt(int n) {
144.1447 +        return 32 - Integer.numberOfLeadingZeros(n);
144.1448 +    }
144.1449 +
144.1450 +    /**
144.1451 +     * Left shift int array a up to len by n bits. Returns the array that
144.1452 +     * results from the shift since space may have to be reallocated.
144.1453 +     */
144.1454 +    private static int[] leftShift(int[] a, int len, int n) {
144.1455 +        int nInts = n >>> 5;
144.1456 +        int nBits = n&0x1F;
144.1457 +        int bitsInHighWord = bitLengthForInt(a[0]);
144.1458 +
144.1459 +        // If shift can be done without recopy, do so
144.1460 +        if (n <= (32-bitsInHighWord)) {
144.1461 +            primitiveLeftShift(a, len, nBits);
144.1462 +            return a;
144.1463 +        } else { // Array must be resized
144.1464 +            if (nBits <= (32-bitsInHighWord)) {
144.1465 +                int result[] = new int[nInts+len];
144.1466 +                for (int i=0; i<len; i++)
144.1467 +                    result[i] = a[i];
144.1468 +                primitiveLeftShift(result, result.length, nBits);
144.1469 +                return result;
144.1470 +            } else {
144.1471 +                int result[] = new int[nInts+len+1];
144.1472 +                for (int i=0; i<len; i++)
144.1473 +                    result[i] = a[i];
144.1474 +                primitiveRightShift(result, result.length, 32 - nBits);
144.1475 +                return result;
144.1476 +            }
144.1477 +        }
144.1478 +    }
144.1479 +
144.1480 +    // shifts a up to len right n bits assumes no leading zeros, 0<n<32
144.1481 +    static void primitiveRightShift(int[] a, int len, int n) {
144.1482 +        int n2 = 32 - n;
144.1483 +        for (int i=len-1, c=a[i]; i>0; i--) {
144.1484 +            int b = c;
144.1485 +            c = a[i-1];
144.1486 +            a[i] = (c << n2) | (b >>> n);
144.1487 +        }
144.1488 +        a[0] >>>= n;
144.1489 +    }
144.1490 +
144.1491 +    // shifts a up to len left n bits assumes no leading zeros, 0<=n<32
144.1492 +    static void primitiveLeftShift(int[] a, int len, int n) {
144.1493 +        if (len == 0 || n == 0)
144.1494 +            return;
144.1495 +
144.1496 +        int n2 = 32 - n;
144.1497 +        for (int i=0, c=a[i], m=i+len-1; i<m; i++) {
144.1498 +            int b = c;
144.1499 +            c = a[i+1];
144.1500 +            a[i] = (b << n) | (c >>> n2);
144.1501 +        }
144.1502 +        a[len-1] <<= n;
144.1503 +    }
144.1504 +
144.1505 +    /**
144.1506 +     * Calculate bitlength of contents of the first len elements an int array,
144.1507 +     * assuming there are no leading zero ints.
144.1508 +     */
144.1509 +    private static int bitLength(int[] val, int len) {
144.1510 +        if (len == 0)
144.1511 +            return 0;
144.1512 +        return ((len - 1) << 5) + bitLengthForInt(val[0]);
144.1513 +    }
144.1514 +
144.1515 +    /**
144.1516 +     * Returns a BigInteger whose value is the absolute value of this
144.1517 +     * BigInteger.
144.1518 +     *
144.1519 +     * @return {@code abs(this)}
144.1520 +     */
144.1521 +    public BigInteger abs() {
144.1522 +        return (signum >= 0 ? this : this.negate());
144.1523 +    }
144.1524 +
144.1525 +    /**
144.1526 +     * Returns a BigInteger whose value is {@code (-this)}.
144.1527 +     *
144.1528 +     * @return {@code -this}
144.1529 +     */
144.1530 +    public BigInteger negate() {
144.1531 +        return new BigInteger(this.mag, -this.signum);
144.1532 +    }
144.1533 +
144.1534 +    /**
144.1535 +     * Returns the signum function of this BigInteger.
144.1536 +     *
144.1537 +     * @return -1, 0 or 1 as the value of this BigInteger is negative, zero or
144.1538 +     *         positive.
144.1539 +     */
144.1540 +    public int signum() {
144.1541 +        return this.signum;
144.1542 +    }
144.1543 +
144.1544 +    // Modular Arithmetic Operations
144.1545 +
144.1546 +    /**
144.1547 +     * Returns a BigInteger whose value is {@code (this mod m}).  This method
144.1548 +     * differs from {@code remainder} in that it always returns a
144.1549 +     * <i>non-negative</i> BigInteger.
144.1550 +     *
144.1551 +     * @param  m the modulus.
144.1552 +     * @return {@code this mod m}
144.1553 +     * @throws ArithmeticException {@code m} &le; 0
144.1554 +     * @see    #remainder
144.1555 +     */
144.1556 +    public BigInteger mod(BigInteger m) {
144.1557 +        if (m.signum <= 0)
144.1558 +            throw new ArithmeticException("BigInteger: modulus not positive");
144.1559 +
144.1560 +        BigInteger result = this.remainder(m);
144.1561 +        return (result.signum >= 0 ? result : result.add(m));
144.1562 +    }
144.1563 +
144.1564 +    /**
144.1565 +     * Returns a BigInteger whose value is
144.1566 +     * <tt>(this<sup>exponent</sup> mod m)</tt>.  (Unlike {@code pow}, this
144.1567 +     * method permits negative exponents.)
144.1568 +     *
144.1569 +     * @param  exponent the exponent.
144.1570 +     * @param  m the modulus.
144.1571 +     * @return <tt>this<sup>exponent</sup> mod m</tt>
144.1572 +     * @throws ArithmeticException {@code m} &le; 0 or the exponent is
144.1573 +     *         negative and this BigInteger is not <i>relatively
144.1574 +     *         prime</i> to {@code m}.
144.1575 +     * @see    #modInverse
144.1576 +     */
144.1577 +    public BigInteger modPow(BigInteger exponent, BigInteger m) {
144.1578 +        if (m.signum <= 0)
144.1579 +            throw new ArithmeticException("BigInteger: modulus not positive");
144.1580 +
144.1581 +        // Trivial cases
144.1582 +        if (exponent.signum == 0)
144.1583 +            return (m.equals(ONE) ? ZERO : ONE);
144.1584 +
144.1585 +        if (this.equals(ONE))
144.1586 +            return (m.equals(ONE) ? ZERO : ONE);
144.1587 +
144.1588 +        if (this.equals(ZERO) && exponent.signum >= 0)
144.1589 +            return ZERO;
144.1590 +
144.1591 +        if (this.equals(negConst[1]) && (!exponent.testBit(0)))
144.1592 +            return (m.equals(ONE) ? ZERO : ONE);
144.1593 +
144.1594 +        boolean invertResult;
144.1595 +        if ((invertResult = (exponent.signum < 0)))
144.1596 +            exponent = exponent.negate();
144.1597 +
144.1598 +        BigInteger base = (this.signum < 0 || this.compareTo(m) >= 0
144.1599 +                           ? this.mod(m) : this);
144.1600 +        BigInteger result;
144.1601 +        if (m.testBit(0)) { // odd modulus
144.1602 +            result = base.oddModPow(exponent, m);
144.1603 +        } else {
144.1604 +            /*
144.1605 +             * Even modulus.  Tear it into an "odd part" (m1) and power of two
144.1606 +             * (m2), exponentiate mod m1, manually exponentiate mod m2, and
144.1607 +             * use Chinese Remainder Theorem to combine results.
144.1608 +             */
144.1609 +
144.1610 +            // Tear m apart into odd part (m1) and power of 2 (m2)
144.1611 +            int p = m.getLowestSetBit();   // Max pow of 2 that divides m
144.1612 +
144.1613 +            BigInteger m1 = m.shiftRight(p);  // m/2**p
144.1614 +            BigInteger m2 = ONE.shiftLeft(p); // 2**p
144.1615 +
144.1616 +            // Calculate new base from m1
144.1617 +            BigInteger base2 = (this.signum < 0 || this.compareTo(m1) >= 0
144.1618 +                                ? this.mod(m1) : this);
144.1619 +
144.1620 +            // Caculate (base ** exponent) mod m1.
144.1621 +            BigInteger a1 = (m1.equals(ONE) ? ZERO :
144.1622 +                             base2.oddModPow(exponent, m1));
144.1623 +
144.1624 +            // Calculate (this ** exponent) mod m2
144.1625 +            BigInteger a2 = base.modPow2(exponent, p);
144.1626 +
144.1627 +            // Combine results using Chinese Remainder Theorem
144.1628 +            BigInteger y1 = m2.modInverse(m1);
144.1629 +            BigInteger y2 = m1.modInverse(m2);
144.1630 +
144.1631 +            result = a1.multiply(m2).multiply(y1).add
144.1632 +                     (a2.multiply(m1).multiply(y2)).mod(m);
144.1633 +        }
144.1634 +
144.1635 +        return (invertResult ? result.modInverse(m) : result);
144.1636 +    }
144.1637 +
144.1638 +    static int[] bnExpModThreshTable = {7, 25, 81, 241, 673, 1793,
144.1639 +                                                Integer.MAX_VALUE}; // Sentinel
144.1640 +
144.1641 +    /**
144.1642 +     * Returns a BigInteger whose value is x to the power of y mod z.
144.1643 +     * Assumes: z is odd && x < z.
144.1644 +     */
144.1645 +    private BigInteger oddModPow(BigInteger y, BigInteger z) {
144.1646 +    /*
144.1647 +     * The algorithm is adapted from Colin Plumb's C library.
144.1648 +     *
144.1649 +     * The window algorithm:
144.1650 +     * The idea is to keep a running product of b1 = n^(high-order bits of exp)
144.1651 +     * and then keep appending exponent bits to it.  The following patterns
144.1652 +     * apply to a 3-bit window (k = 3):
144.1653 +     * To append   0: square
144.1654 +     * To append   1: square, multiply by n^1
144.1655 +     * To append  10: square, multiply by n^1, square
144.1656 +     * To append  11: square, square, multiply by n^3
144.1657 +     * To append 100: square, multiply by n^1, square, square
144.1658 +     * To append 101: square, square, square, multiply by n^5
144.1659 +     * To append 110: square, square, multiply by n^3, square
144.1660 +     * To append 111: square, square, square, multiply by n^7
144.1661 +     *
144.1662 +     * Since each pattern involves only one multiply, the longer the pattern
144.1663 +     * the better, except that a 0 (no multiplies) can be appended directly.
144.1664 +     * We precompute a table of odd powers of n, up to 2^k, and can then
144.1665 +     * multiply k bits of exponent at a time.  Actually, assuming random
144.1666 +     * exponents, there is on average one zero bit between needs to
144.1667 +     * multiply (1/2 of the time there's none, 1/4 of the time there's 1,
144.1668 +     * 1/8 of the time, there's 2, 1/32 of the time, there's 3, etc.), so
144.1669 +     * you have to do one multiply per k+1 bits of exponent.
144.1670 +     *
144.1671 +     * The loop walks down the exponent, squaring the result buffer as
144.1672 +     * it goes.  There is a wbits+1 bit lookahead buffer, buf, that is
144.1673 +     * filled with the upcoming exponent bits.  (What is read after the
144.1674 +     * end of the exponent is unimportant, but it is filled with zero here.)
144.1675 +     * When the most-significant bit of this buffer becomes set, i.e.
144.1676 +     * (buf & tblmask) != 0, we have to decide what pattern to multiply
144.1677 +     * by, and when to do it.  We decide, remember to do it in future
144.1678 +     * after a suitable number of squarings have passed (e.g. a pattern
144.1679 +     * of "100" in the buffer requires that we multiply by n^1 immediately;
144.1680 +     * a pattern of "110" calls for multiplying by n^3 after one more
144.1681 +     * squaring), clear the buffer, and continue.
144.1682 +     *
144.1683 +     * When we start, there is one more optimization: the result buffer
144.1684 +     * is implcitly one, so squaring it or multiplying by it can be
144.1685 +     * optimized away.  Further, if we start with a pattern like "100"
144.1686 +     * in the lookahead window, rather than placing n into the buffer
144.1687 +     * and then starting to square it, we have already computed n^2
144.1688 +     * to compute the odd-powers table, so we can place that into
144.1689 +     * the buffer and save a squaring.
144.1690 +     *
144.1691 +     * This means that if you have a k-bit window, to compute n^z,
144.1692 +     * where z is the high k bits of the exponent, 1/2 of the time
144.1693 +     * it requires no squarings.  1/4 of the time, it requires 1
144.1694 +     * squaring, ... 1/2^(k-1) of the time, it reqires k-2 squarings.
144.1695 +     * And the remaining 1/2^(k-1) of the time, the top k bits are a
144.1696 +     * 1 followed by k-1 0 bits, so it again only requires k-2
144.1697 +     * squarings, not k-1.  The average of these is 1.  Add that
144.1698 +     * to the one squaring we have to do to compute the table,
144.1699 +     * and you'll see that a k-bit window saves k-2 squarings
144.1700 +     * as well as reducing the multiplies.  (It actually doesn't
144.1701 +     * hurt in the case k = 1, either.)
144.1702 +     */
144.1703 +        // Special case for exponent of one
144.1704 +        if (y.equals(ONE))
144.1705 +            return this;
144.1706 +
144.1707 +        // Special case for base of zero
144.1708 +        if (signum==0)
144.1709 +            return ZERO;
144.1710 +
144.1711 +        int[] base = mag.clone();
144.1712 +        int[] exp = y.mag;
144.1713 +        int[] mod = z.mag;
144.1714 +        int modLen = mod.length;
144.1715 +
144.1716 +        // Select an appropriate window size
144.1717 +        int wbits = 0;
144.1718 +        int ebits = bitLength(exp, exp.length);
144.1719 +        // if exponent is 65537 (0x10001), use minimum window size
144.1720 +        if ((ebits != 17) || (exp[0] != 65537)) {
144.1721 +            while (ebits > bnExpModThreshTable[wbits]) {
144.1722 +                wbits++;
144.1723 +            }
144.1724 +        }
144.1725 +
144.1726 +        // Calculate appropriate table size
144.1727 +        int tblmask = 1 << wbits;
144.1728 +
144.1729 +        // Allocate table for precomputed odd powers of base in Montgomery form
144.1730 +        int[][] table = new int[tblmask][];
144.1731 +        for (int i=0; i<tblmask; i++)
144.1732 +            table[i] = new int[modLen];
144.1733 +
144.1734 +        // Compute the modular inverse
144.1735 +        int inv = -MutableBigInteger.inverseMod32(mod[modLen-1]);
144.1736 +
144.1737 +        // Convert base to Montgomery form
144.1738 +        int[] a = leftShift(base, base.length, modLen << 5);
144.1739 +
144.1740 +        MutableBigInteger q = new MutableBigInteger(),
144.1741 +                          a2 = new MutableBigInteger(a),
144.1742 +                          b2 = new MutableBigInteger(mod);
144.1743 +
144.1744 +        MutableBigInteger r= a2.divide(b2, q);
144.1745 +        table[0] = r.toIntArray();
144.1746 +
144.1747 +        // Pad table[0] with leading zeros so its length is at least modLen
144.1748 +        if (table[0].length < modLen) {
144.1749 +           int offset = modLen - table[0].length;
144.1750 +           int[] t2 = new int[modLen];
144.1751 +           for (int i=0; i<table[0].length; i++)
144.1752 +               t2[i+offset] = table[0][i];
144.1753 +           table[0] = t2;
144.1754 +        }
144.1755 +
144.1756 +        // Set b to the square of the base
144.1757 +        int[] b = squareToLen(table[0], modLen, null);
144.1758 +        b = montReduce(b, mod, modLen, inv);
144.1759 +
144.1760 +        // Set t to high half of b
144.1761 +        int[] t = new int[modLen];
144.1762 +        for(int i=0; i<modLen; i++)
144.1763 +            t[i] = b[i];
144.1764 +
144.1765 +        // Fill in the table with odd powers of the base
144.1766 +        for (int i=1; i<tblmask; i++) {
144.1767 +            int[] prod = multiplyToLen(t, modLen, table[i-1], modLen, null);
144.1768 +            table[i] = montReduce(prod, mod, modLen, inv);
144.1769 +        }
144.1770 +
144.1771 +        // Pre load the window that slides over the exponent
144.1772 +        int bitpos = 1 << ((ebits-1) & (32-1));
144.1773 +
144.1774 +        int buf = 0;
144.1775 +        int elen = exp.length;
144.1776 +        int eIndex = 0;
144.1777 +        for (int i = 0; i <= wbits; i++) {
144.1778 +            buf = (buf << 1) | (((exp[eIndex] & bitpos) != 0)?1:0);
144.1779 +            bitpos >>>= 1;
144.1780 +            if (bitpos == 0) {
144.1781 +                eIndex++;
144.1782 +                bitpos = 1 << (32-1);
144.1783 +                elen--;
144.1784 +            }
144.1785 +        }
144.1786 +
144.1787 +        int multpos = ebits;
144.1788 +
144.1789 +        // The first iteration, which is hoisted out of the main loop
144.1790 +        ebits--;
144.1791 +        boolean isone = true;
144.1792 +
144.1793 +        multpos = ebits - wbits;
144.1794 +        while ((buf & 1) == 0) {
144.1795 +            buf >>>= 1;
144.1796 +            multpos++;
144.1797 +        }
144.1798 +
144.1799 +        int[] mult = table[buf >>> 1];
144.1800 +
144.1801 +        buf = 0;
144.1802 +        if (multpos == ebits)
144.1803 +            isone = false;
144.1804 +
144.1805 +        // The main loop
144.1806 +        while(true) {
144.1807 +            ebits--;
144.1808 +            // Advance the window
144.1809 +            buf <<= 1;
144.1810 +
144.1811 +            if (elen != 0) {
144.1812 +                buf |= ((exp[eIndex] & bitpos) != 0) ? 1 : 0;
144.1813 +                bitpos >>>= 1;
144.1814 +                if (bitpos == 0) {
144.1815 +                    eIndex++;
144.1816 +                    bitpos = 1 << (32-1);
144.1817 +                    elen--;
144.1818 +                }
144.1819 +            }
144.1820 +
144.1821 +            // Examine the window for pending multiplies
144.1822 +            if ((buf & tblmask) != 0) {
144.1823 +                multpos = ebits - wbits;
144.1824 +                while ((buf & 1) == 0) {
144.1825 +                    buf >>>= 1;
144.1826 +                    multpos++;
144.1827 +                }
144.1828 +                mult = table[buf >>> 1];
144.1829 +                buf = 0;
144.1830 +            }
144.1831 +
144.1832 +            // Perform multiply
144.1833 +            if (ebits == multpos) {
144.1834 +                if (isone) {
144.1835 +                    b = mult.clone();
144.1836 +                    isone = false;
144.1837 +                } else {
144.1838 +                    t = b;
144.1839 +                    a = multiplyToLen(t, modLen, mult, modLen, a);
144.1840 +                    a = montReduce(a, mod, modLen, inv);
144.1841 +                    t = a; a = b; b = t;
144.1842 +                }
144.1843 +            }
144.1844 +
144.1845 +            // Check if done
144.1846 +            if (ebits == 0)
144.1847 +                break;
144.1848 +
144.1849 +            // Square the input
144.1850 +            if (!isone) {
144.1851 +                t = b;
144.1852 +                a = squareToLen(t, modLen, a);
144.1853 +                a = montReduce(a, mod, modLen, inv);
144.1854 +                t = a; a = b; b = t;
144.1855 +            }
144.1856 +        }
144.1857 +
144.1858 +        // Convert result out of Montgomery form and return
144.1859 +        int[] t2 = new int[2*modLen];
144.1860 +        for(int i=0; i<modLen; i++)
144.1861 +            t2[i+modLen] = b[i];
144.1862 +
144.1863 +        b = montReduce(t2, mod, modLen, inv);
144.1864 +
144.1865 +        t2 = new int[modLen];
144.1866 +        for(int i=0; i<modLen; i++)
144.1867 +            t2[i] = b[i];
144.1868 +
144.1869 +        return new BigInteger(1, t2);
144.1870 +    }
144.1871 +
144.1872 +    /**
144.1873 +     * Montgomery reduce n, modulo mod.  This reduces modulo mod and divides
144.1874 +     * by 2^(32*mlen). Adapted from Colin Plumb's C library.
144.1875 +     */
144.1876 +    private static int[] montReduce(int[] n, int[] mod, int mlen, int inv) {
144.1877 +        int c=0;
144.1878 +        int len = mlen;
144.1879 +        int offset=0;
144.1880 +
144.1881 +        do {
144.1882 +            int nEnd = n[n.length-1-offset];
144.1883 +            int carry = mulAdd(n, mod, offset, mlen, inv * nEnd);
144.1884 +            c += addOne(n, offset, mlen, carry);
144.1885 +            offset++;
144.1886 +        } while(--len > 0);
144.1887 +
144.1888 +        while(c>0)
144.1889 +            c += subN(n, mod, mlen);
144.1890 +
144.1891 +        while (intArrayCmpToLen(n, mod, mlen) >= 0)
144.1892 +            subN(n, mod, mlen);
144.1893 +
144.1894 +        return n;
144.1895 +    }
144.1896 +
144.1897 +
144.1898 +    /*
144.1899 +     * Returns -1, 0 or +1 as big-endian unsigned int array arg1 is less than,
144.1900 +     * equal to, or greater than arg2 up to length len.
144.1901 +     */
144.1902 +    private static int intArrayCmpToLen(int[] arg1, int[] arg2, int len) {
144.1903 +        for (int i=0; i<len; i++) {
144.1904 +            long b1 = arg1[i] & LONG_MASK;
144.1905 +            long b2 = arg2[i] & LONG_MASK;
144.1906 +            if (b1 < b2)
144.1907 +                return -1;
144.1908 +            if (b1 > b2)
144.1909 +                return 1;
144.1910 +        }
144.1911 +        return 0;
144.1912 +    }
144.1913 +
144.1914 +    /**
144.1915 +     * Subtracts two numbers of same length, returning borrow.
144.1916 +     */
144.1917 +    private static int subN(int[] a, int[] b, int len) {
144.1918 +        long sum = 0;
144.1919 +
144.1920 +        while(--len >= 0) {
144.1921 +            sum = (a[len] & LONG_MASK) -
144.1922 +                 (b[len] & LONG_MASK) + (sum >> 32);
144.1923 +            a[len] = (int)sum;
144.1924 +        }
144.1925 +
144.1926 +        return (int)(sum >> 32);
144.1927 +    }
144.1928 +
144.1929 +    /**
144.1930 +     * Multiply an array by one word k and add to result, return the carry
144.1931 +     */
144.1932 +    static int mulAdd(int[] out, int[] in, int offset, int len, int k) {
144.1933 +        long kLong = k & LONG_MASK;
144.1934 +        long carry = 0;
144.1935 +
144.1936 +        offset = out.length-offset - 1;
144.1937 +        for (int j=len-1; j >= 0; j--) {
144.1938 +            long product = (in[j] & LONG_MASK) * kLong +
144.1939 +                           (out[offset] & LONG_MASK) + carry;
144.1940 +            out[offset--] = (int)product;
144.1941 +            carry = product >>> 32;
144.1942 +        }
144.1943 +        return (int)carry;
144.1944 +    }
144.1945 +
144.1946 +    /**
144.1947 +     * Add one word to the number a mlen words into a. Return the resulting
144.1948 +     * carry.
144.1949 +     */
144.1950 +    static int addOne(int[] a, int offset, int mlen, int carry) {
144.1951 +        offset = a.length-1-mlen-offset;
144.1952 +        long t = (a[offset] & LONG_MASK) + (carry & LONG_MASK);
144.1953 +
144.1954 +        a[offset] = (int)t;
144.1955 +        if ((t >>> 32) == 0)
144.1956 +            return 0;
144.1957 +        while (--mlen >= 0) {
144.1958 +            if (--offset < 0) { // Carry out of number
144.1959 +                return 1;
144.1960 +            } else {
144.1961 +                a[offset]++;
144.1962 +                if (a[offset] != 0)
144.1963 +                    return 0;
144.1964 +            }
144.1965 +        }
144.1966 +        return 1;
144.1967 +    }
144.1968 +
144.1969 +    /**
144.1970 +     * Returns a BigInteger whose value is (this ** exponent) mod (2**p)
144.1971 +     */
144.1972 +    private BigInteger modPow2(BigInteger exponent, int p) {
144.1973 +        /*
144.1974 +         * Perform exponentiation using repeated squaring trick, chopping off
144.1975 +         * high order bits as indicated by modulus.
144.1976 +         */
144.1977 +        BigInteger result = valueOf(1);
144.1978 +        BigInteger baseToPow2 = this.mod2(p);
144.1979 +        int expOffset = 0;
144.1980 +
144.1981 +        int limit = exponent.bitLength();
144.1982 +
144.1983 +        if (this.testBit(0))
144.1984 +           limit = (p-1) < limit ? (p-1) : limit;
144.1985 +
144.1986 +        while (expOffset < limit) {
144.1987 +            if (exponent.testBit(expOffset))
144.1988 +                result = result.multiply(baseToPow2).mod2(p);
144.1989 +            expOffset++;
144.1990 +            if (expOffset < limit)
144.1991 +                baseToPow2 = baseToPow2.square().mod2(p);
144.1992 +        }
144.1993 +
144.1994 +        return result;
144.1995 +    }
144.1996 +
144.1997 +    /**
144.1998 +     * Returns a BigInteger whose value is this mod(2**p).
144.1999 +     * Assumes that this {@code BigInteger >= 0} and {@code p > 0}.
144.2000 +     */
144.2001 +    private BigInteger mod2(int p) {
144.2002 +        if (bitLength() <= p)
144.2003 +            return this;
144.2004 +
144.2005 +        // Copy remaining ints of mag
144.2006 +        int numInts = (p + 31) >>> 5;
144.2007 +        int[] mag = new int[numInts];
144.2008 +        for (int i=0; i<numInts; i++)
144.2009 +            mag[i] = this.mag[i + (this.mag.length - numInts)];
144.2010 +
144.2011 +        // Mask out any excess bits
144.2012 +        int excessBits = (numInts << 5) - p;
144.2013 +        mag[0] &= (1L << (32-excessBits)) - 1;
144.2014 +
144.2015 +        return (mag[0]==0 ? new BigInteger(1, mag) : new BigInteger(mag, 1));
144.2016 +    }
144.2017 +
144.2018 +    /**
144.2019 +     * Returns a BigInteger whose value is {@code (this}<sup>-1</sup> {@code mod m)}.
144.2020 +     *
144.2021 +     * @param  m the modulus.
144.2022 +     * @return {@code this}<sup>-1</sup> {@code mod m}.
144.2023 +     * @throws ArithmeticException {@code  m} &le; 0, or this BigInteger
144.2024 +     *         has no multiplicative inverse mod m (that is, this BigInteger
144.2025 +     *         is not <i>relatively prime</i> to m).
144.2026 +     */
144.2027 +    public BigInteger modInverse(BigInteger m) {
144.2028 +        if (m.signum != 1)
144.2029 +            throw new ArithmeticException("BigInteger: modulus not positive");
144.2030 +
144.2031 +        if (m.equals(ONE))
144.2032 +            return ZERO;
144.2033 +
144.2034 +        // Calculate (this mod m)
144.2035 +        BigInteger modVal = this;
144.2036 +        if (signum < 0 || (this.compareMagnitude(m) >= 0))
144.2037 +            modVal = this.mod(m);
144.2038 +
144.2039 +        if (modVal.equals(ONE))
144.2040 +            return ONE;
144.2041 +
144.2042 +        MutableBigInteger a = new MutableBigInteger(modVal);
144.2043 +        MutableBigInteger b = new MutableBigInteger(m);
144.2044 +
144.2045 +        MutableBigInteger result = a.mutableModInverse(b);
144.2046 +        return result.toBigInteger(1);
144.2047 +    }
144.2048 +
144.2049 +    // Shift Operations
144.2050 +
144.2051 +    /**
144.2052 +     * Returns a BigInteger whose value is {@code (this << n)}.
144.2053 +     * The shift distance, {@code n}, may be negative, in which case
144.2054 +     * this method performs a right shift.
144.2055 +     * (Computes <tt>floor(this * 2<sup>n</sup>)</tt>.)
144.2056 +     *
144.2057 +     * @param  n shift distance, in bits.
144.2058 +     * @return {@code this << n}
144.2059 +     * @throws ArithmeticException if the shift distance is {@code
144.2060 +     *         Integer.MIN_VALUE}.
144.2061 +     * @see #shiftRight
144.2062 +     */
144.2063 +    public BigInteger shiftLeft(int n) {
144.2064 +        if (signum == 0)
144.2065 +            return ZERO;
144.2066 +        if (n==0)
144.2067 +            return this;
144.2068 +        if (n<0) {
144.2069 +            if (n == Integer.MIN_VALUE) {
144.2070 +                throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
144.2071 +            } else {
144.2072 +                return shiftRight(-n);
144.2073 +            }
144.2074 +        }
144.2075 +
144.2076 +        int nInts = n >>> 5;
144.2077 +        int nBits = n & 0x1f;
144.2078 +        int magLen = mag.length;
144.2079 +        int newMag[] = null;
144.2080 +
144.2081 +        if (nBits == 0) {
144.2082 +            newMag = new int[magLen + nInts];
144.2083 +            for (int i=0; i<magLen; i++)
144.2084 +                newMag[i] = mag[i];
144.2085 +        } else {
144.2086 +            int i = 0;
144.2087 +            int nBits2 = 32 - nBits;
144.2088 +            int highBits = mag[0] >>> nBits2;
144.2089 +            if (highBits != 0) {
144.2090 +                newMag = new int[magLen + nInts + 1];
144.2091 +                newMag[i++] = highBits;
144.2092 +            } else {
144.2093 +                newMag = new int[magLen + nInts];
144.2094 +            }
144.2095 +            int j=0;
144.2096 +            while (j < magLen-1)
144.2097 +                newMag[i++] = mag[j++] << nBits | mag[j] >>> nBits2;
144.2098 +            newMag[i] = mag[j] << nBits;
144.2099 +        }
144.2100 +
144.2101 +        return new BigInteger(newMag, signum);
144.2102 +    }
144.2103 +
144.2104 +    /**
144.2105 +     * Returns a BigInteger whose value is {@code (this >> n)}.  Sign
144.2106 +     * extension is performed.  The shift distance, {@code n}, may be
144.2107 +     * negative, in which case this method performs a left shift.
144.2108 +     * (Computes <tt>floor(this / 2<sup>n</sup>)</tt>.)
144.2109 +     *
144.2110 +     * @param  n shift distance, in bits.
144.2111 +     * @return {@code this >> n}
144.2112 +     * @throws ArithmeticException if the shift distance is {@code
144.2113 +     *         Integer.MIN_VALUE}.
144.2114 +     * @see #shiftLeft
144.2115 +     */
144.2116 +    public BigInteger shiftRight(int n) {
144.2117 +        if (n==0)
144.2118 +            return this;
144.2119 +        if (n<0) {
144.2120 +            if (n == Integer.MIN_VALUE) {
144.2121 +                throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
144.2122 +            } else {
144.2123 +                return shiftLeft(-n);
144.2124 +            }
144.2125 +        }
144.2126 +
144.2127 +        int nInts = n >>> 5;
144.2128 +        int nBits = n & 0x1f;
144.2129 +        int magLen = mag.length;
144.2130 +        int newMag[] = null;
144.2131 +
144.2132 +        // Special case: entire contents shifted off the end
144.2133 +        if (nInts >= magLen)
144.2134 +            return (signum >= 0 ? ZERO : negConst[1]);
144.2135 +
144.2136 +        if (nBits == 0) {
144.2137 +            int newMagLen = magLen - nInts;
144.2138 +            newMag = new int[newMagLen];
144.2139 +            for (int i=0; i<newMagLen; i++)
144.2140 +                newMag[i] = mag[i];
144.2141 +        } else {
144.2142 +            int i = 0;
144.2143 +            int highBits = mag[0] >>> nBits;
144.2144 +            if (highBits != 0) {
144.2145 +                newMag = new int[magLen - nInts];
144.2146 +                newMag[i++] = highBits;
144.2147 +            } else {
144.2148 +                newMag = new int[magLen - nInts -1];
144.2149 +            }
144.2150 +
144.2151 +            int nBits2 = 32 - nBits;
144.2152 +            int j=0;
144.2153 +            while (j < magLen - nInts - 1)
144.2154 +                newMag[i++] = (mag[j++] << nBits2) | (mag[j] >>> nBits);
144.2155 +        }
144.2156 +
144.2157 +        if (signum < 0) {
144.2158 +            // Find out whether any one-bits were shifted off the end.
144.2159 +            boolean onesLost = false;
144.2160 +            for (int i=magLen-1, j=magLen-nInts; i>=j && !onesLost; i--)
144.2161 +                onesLost = (mag[i] != 0);
144.2162 +            if (!onesLost && nBits != 0)
144.2163 +                onesLost = (mag[magLen - nInts - 1] << (32 - nBits) != 0);
144.2164 +
144.2165 +            if (onesLost)
144.2166 +                newMag = javaIncrement(newMag);
144.2167 +        }
144.2168 +
144.2169 +        return new BigInteger(newMag, signum);
144.2170 +    }
144.2171 +
144.2172 +    int[] javaIncrement(int[] val) {
144.2173 +        int lastSum = 0;
144.2174 +        for (int i=val.length-1;  i >= 0 && lastSum == 0; i--)
144.2175 +            lastSum = (val[i] += 1);
144.2176 +        if (lastSum == 0) {
144.2177 +            val = new int[val.length+1];
144.2178 +            val[0] = 1;
144.2179 +        }
144.2180 +        return val;
144.2181 +    }
144.2182 +
144.2183 +    // Bitwise Operations
144.2184 +
144.2185 +    /**
144.2186 +     * Returns a BigInteger whose value is {@code (this & val)}.  (This
144.2187 +     * method returns a negative BigInteger if and only if this and val are
144.2188 +     * both negative.)
144.2189 +     *
144.2190 +     * @param val value to be AND'ed with this BigInteger.
144.2191 +     * @return {@code this & val}
144.2192 +     */
144.2193 +    public BigInteger and(BigInteger val) {
144.2194 +        int[] result = new int[Math.max(intLength(), val.intLength())];
144.2195 +        for (int i=0; i<result.length; i++)
144.2196 +            result[i] = (getInt(result.length-i-1)
144.2197 +                         & val.getInt(result.length-i-1));
144.2198 +
144.2199 +        return valueOf(result);
144.2200 +    }
144.2201 +
144.2202 +    /**
144.2203 +     * Returns a BigInteger whose value is {@code (this | val)}.  (This method
144.2204 +     * returns a negative BigInteger if and only if either this or val is
144.2205 +     * negative.)
144.2206 +     *
144.2207 +     * @param val value to be OR'ed with this BigInteger.
144.2208 +     * @return {@code this | val}
144.2209 +     */
144.2210 +    public BigInteger or(BigInteger val) {
144.2211 +        int[] result = new int[Math.max(intLength(), val.intLength())];
144.2212 +        for (int i=0; i<result.length; i++)
144.2213 +            result[i] = (getInt(result.length-i-1)
144.2214 +                         | val.getInt(result.length-i-1));
144.2215 +
144.2216 +        return valueOf(result);
144.2217 +    }
144.2218 +
144.2219 +    /**
144.2220 +     * Returns a BigInteger whose value is {@code (this ^ val)}.  (This method
144.2221 +     * returns a negative BigInteger if and only if exactly one of this and
144.2222 +     * val are negative.)
144.2223 +     *
144.2224 +     * @param val value to be XOR'ed with this BigInteger.
144.2225 +     * @return {@code this ^ val}
144.2226 +     */
144.2227 +    public BigInteger xor(BigInteger val) {
144.2228 +        int[] result = new int[Math.max(intLength(), val.intLength())];
144.2229 +        for (int i=0; i<result.length; i++)
144.2230 +            result[i] = (getInt(result.length-i-1)
144.2231 +                         ^ val.getInt(result.length-i-1));
144.2232 +
144.2233 +        return valueOf(result);
144.2234 +    }
144.2235 +
144.2236 +    /**
144.2237 +     * Returns a BigInteger whose value is {@code (~this)}.  (This method
144.2238 +     * returns a negative value if and only if this BigInteger is
144.2239 +     * non-negative.)
144.2240 +     *
144.2241 +     * @return {@code ~this}
144.2242 +     */
144.2243 +    public BigInteger not() {
144.2244 +        int[] result = new int[intLength()];
144.2245 +        for (int i=0; i<result.length; i++)
144.2246 +            result[i] = ~getInt(result.length-i-1);
144.2247 +
144.2248 +        return valueOf(result);
144.2249 +    }
144.2250 +
144.2251 +    /**
144.2252 +     * Returns a BigInteger whose value is {@code (this & ~val)}.  This
144.2253 +     * method, which is equivalent to {@code and(val.not())}, is provided as
144.2254 +     * a convenience for masking operations.  (This method returns a negative
144.2255 +     * BigInteger if and only if {@code this} is negative and {@code val} is
144.2256 +     * positive.)
144.2257 +     *
144.2258 +     * @param val value to be complemented and AND'ed with this BigInteger.
144.2259 +     * @return {@code this & ~val}
144.2260 +     */
144.2261 +    public BigInteger andNot(BigInteger val) {
144.2262 +        int[] result = new int[Math.max(intLength(), val.intLength())];
144.2263 +        for (int i=0; i<result.length; i++)
144.2264 +            result[i] = (getInt(result.length-i-1)
144.2265 +                         & ~val.getInt(result.length-i-1));
144.2266 +
144.2267 +        return valueOf(result);
144.2268 +    }
144.2269 +
144.2270 +
144.2271 +    // Single Bit Operations
144.2272 +
144.2273 +    /**
144.2274 +     * Returns {@code true} if and only if the designated bit is set.
144.2275 +     * (Computes {@code ((this & (1<<n)) != 0)}.)
144.2276 +     *
144.2277 +     * @param  n index of bit to test.
144.2278 +     * @return {@code true} if and only if the designated bit is set.
144.2279 +     * @throws ArithmeticException {@code n} is negative.
144.2280 +     */
144.2281 +    public boolean testBit(int n) {
144.2282 +        if (n<0)
144.2283 +            throw new ArithmeticException("Negative bit address");
144.2284 +
144.2285 +        return (getInt(n >>> 5) & (1 << (n & 31))) != 0;
144.2286 +    }
144.2287 +
144.2288 +    /**
144.2289 +     * Returns a BigInteger whose value is equivalent to this BigInteger
144.2290 +     * with the designated bit set.  (Computes {@code (this | (1<<n))}.)
144.2291 +     *
144.2292 +     * @param  n index of bit to set.
144.2293 +     * @return {@code this | (1<<n)}
144.2294 +     * @throws ArithmeticException {@code n} is negative.
144.2295 +     */
144.2296 +    public BigInteger setBit(int n) {
144.2297 +        if (n<0)
144.2298 +            throw new ArithmeticException("Negative bit address");
144.2299 +
144.2300 +        int intNum = n >>> 5;
144.2301 +        int[] result = new int[Math.max(intLength(), intNum+2)];
144.2302 +
144.2303 +        for (int i=0; i<result.length; i++)
144.2304 +            result[result.length-i-1] = getInt(i);
144.2305 +
144.2306 +        result[result.length-intNum-1] |= (1 << (n & 31));
144.2307 +
144.2308 +        return valueOf(result);
144.2309 +    }
144.2310 +
144.2311 +    /**
144.2312 +     * Returns a BigInteger whose value is equivalent to this BigInteger
144.2313 +     * with the designated bit cleared.
144.2314 +     * (Computes {@code (this & ~(1<<n))}.)
144.2315 +     *
144.2316 +     * @param  n index of bit to clear.
144.2317 +     * @return {@code this & ~(1<<n)}
144.2318 +     * @throws ArithmeticException {@code n} is negative.
144.2319 +     */
144.2320 +    public BigInteger clearBit(int n) {
144.2321 +        if (n<0)
144.2322 +            throw new ArithmeticException("Negative bit address");
144.2323 +
144.2324 +        int intNum = n >>> 5;
144.2325 +        int[] result = new int[Math.max(intLength(), ((n + 1) >>> 5) + 1)];
144.2326 +
144.2327 +        for (int i=0; i<result.length; i++)
144.2328 +            result[result.length-i-1] = getInt(i);
144.2329 +
144.2330 +        result[result.length-intNum-1] &= ~(1 << (n & 31));
144.2331 +
144.2332 +        return valueOf(result);
144.2333 +    }
144.2334 +
144.2335 +    /**
144.2336 +     * Returns a BigInteger whose value is equivalent to this BigInteger
144.2337 +     * with the designated bit flipped.
144.2338 +     * (Computes {@code (this ^ (1<<n))}.)
144.2339 +     *
144.2340 +     * @param  n index of bit to flip.
144.2341 +     * @return {@code this ^ (1<<n)}
144.2342 +     * @throws ArithmeticException {@code n} is negative.
144.2343 +     */
144.2344 +    public BigInteger flipBit(int n) {
144.2345 +        if (n<0)
144.2346 +            throw new ArithmeticException("Negative bit address");
144.2347 +
144.2348 +        int intNum = n >>> 5;
144.2349 +        int[] result = new int[Math.max(intLength(), intNum+2)];
144.2350 +
144.2351 +        for (int i=0; i<result.length; i++)
144.2352 +            result[result.length-i-1] = getInt(i);
144.2353 +
144.2354 +        result[result.length-intNum-1] ^= (1 << (n & 31));
144.2355 +
144.2356 +        return valueOf(result);
144.2357 +    }
144.2358 +
144.2359 +    /**
144.2360 +     * Returns the index of the rightmost (lowest-order) one bit in this
144.2361 +     * BigInteger (the number of zero bits to the right of the rightmost
144.2362 +     * one bit).  Returns -1 if this BigInteger contains no one bits.
144.2363 +     * (Computes {@code (this==0? -1 : log2(this & -this))}.)
144.2364 +     *
144.2365 +     * @return index of the rightmost one bit in this BigInteger.
144.2366 +     */
144.2367 +    public int getLowestSetBit() {
144.2368 +        @SuppressWarnings("deprecation") int lsb = lowestSetBit - 2;
144.2369 +        if (lsb == -2) {  // lowestSetBit not initialized yet
144.2370 +            lsb = 0;
144.2371 +            if (signum == 0) {
144.2372 +                lsb -= 1;
144.2373 +            } else {
144.2374 +                // Search for lowest order nonzero int
144.2375 +                int i,b;
144.2376 +                for (i=0; (b = getInt(i))==0; i++)
144.2377 +                    ;
144.2378 +                lsb += (i << 5) + Integer.numberOfTrailingZeros(b);
144.2379 +            }
144.2380 +            lowestSetBit = lsb + 2;
144.2381 +        }
144.2382 +        return lsb;
144.2383 +    }
144.2384 +
144.2385 +
144.2386 +    // Miscellaneous Bit Operations
144.2387 +
144.2388 +    /**
144.2389 +     * Returns the number of bits in the minimal two's-complement
144.2390 +     * representation of this BigInteger, <i>excluding</i> a sign bit.
144.2391 +     * For positive BigIntegers, this is equivalent to the number of bits in
144.2392 +     * the ordinary binary representation.  (Computes
144.2393 +     * {@code (ceil(log2(this < 0 ? -this : this+1)))}.)
144.2394 +     *
144.2395 +     * @return number of bits in the minimal two's-complement
144.2396 +     *         representation of this BigInteger, <i>excluding</i> a sign bit.
144.2397 +     */
144.2398 +    public int bitLength() {
144.2399 +        @SuppressWarnings("deprecation") int n = bitLength - 1;
144.2400 +        if (n == -1) { // bitLength not initialized yet
144.2401 +            int[] m = mag;
144.2402 +            int len = m.length;
144.2403 +            if (len == 0) {
144.2404 +                n = 0; // offset by one to initialize
144.2405 +            }  else {
144.2406 +                // Calculate the bit length of the magnitude
144.2407 +                int magBitLength = ((len - 1) << 5) + bitLengthForInt(mag[0]);
144.2408 +                 if (signum < 0) {
144.2409 +                     // Check if magnitude is a power of two
144.2410 +                     boolean pow2 = (Integer.bitCount(mag[0]) == 1);
144.2411 +                     for(int i=1; i< len && pow2; i++)
144.2412 +                         pow2 = (mag[i] == 0);
144.2413 +
144.2414 +                     n = (pow2 ? magBitLength -1 : magBitLength);
144.2415 +                 } else {
144.2416 +                     n = magBitLength;
144.2417 +                 }
144.2418 +            }
144.2419 +            bitLength = n + 1;
144.2420 +        }
144.2421 +        return n;
144.2422 +    }
144.2423 +
144.2424 +    /**
144.2425 +     * Returns the number of bits in the two's complement representation
144.2426 +     * of this BigInteger that differ from its sign bit.  This method is
144.2427 +     * useful when implementing bit-vector style sets atop BigIntegers.
144.2428 +     *
144.2429 +     * @return number of bits in the two's complement representation
144.2430 +     *         of this BigInteger that differ from its sign bit.
144.2431 +     */
144.2432 +    public int bitCount() {
144.2433 +        @SuppressWarnings("deprecation") int bc = bitCount - 1;
144.2434 +        if (bc == -1) {  // bitCount not initialized yet
144.2435 +            bc = 0;      // offset by one to initialize
144.2436 +            // Count the bits in the magnitude
144.2437 +            for (int i=0; i<mag.length; i++)
144.2438 +                bc += Integer.bitCount(mag[i]);
144.2439 +            if (signum < 0) {
144.2440 +                // Count the trailing zeros in the magnitude
144.2441 +                int magTrailingZeroCount = 0, j;
144.2442 +                for (j=mag.length-1; mag[j]==0; j--)
144.2443 +                    magTrailingZeroCount += 32;
144.2444 +                magTrailingZeroCount += Integer.numberOfTrailingZeros(mag[j]);
144.2445 +                bc += magTrailingZeroCount - 1;
144.2446 +            }
144.2447 +            bitCount = bc + 1;
144.2448 +        }
144.2449 +        return bc;
144.2450 +    }
144.2451 +
144.2452 +    // Primality Testing
144.2453 +
144.2454 +    /**
144.2455 +     * Returns {@code true} if this BigInteger is probably prime,
144.2456 +     * {@code false} if it's definitely composite.  If
144.2457 +     * {@code certainty} is &le; 0, {@code true} is
144.2458 +     * returned.
144.2459 +     *
144.2460 +     * @param  certainty a measure of the uncertainty that the caller is
144.2461 +     *         willing to tolerate: if the call returns {@code true}
144.2462 +     *         the probability that this BigInteger is prime exceeds
144.2463 +     *         (1 - 1/2<sup>{@code certainty}</sup>).  The execution time of
144.2464 +     *         this method is proportional to the value of this parameter.
144.2465 +     * @return {@code true} if this BigInteger is probably prime,
144.2466 +     *         {@code false} if it's definitely composite.
144.2467 +     */
144.2468 +    public boolean isProbablePrime(int certainty) {
144.2469 +        if (certainty <= 0)
144.2470 +            return true;
144.2471 +        BigInteger w = this.abs();
144.2472 +        if (w.equals(TWO))
144.2473 +            return true;
144.2474 +        if (!w.testBit(0) || w.equals(ONE))
144.2475 +            return false;
144.2476 +
144.2477 +        return w.primeToCertainty(certainty, null);
144.2478 +    }
144.2479 +
144.2480 +    // Comparison Operations
144.2481 +
144.2482 +    /**
144.2483 +     * Compares this BigInteger with the specified BigInteger.  This
144.2484 +     * method is provided in preference to individual methods for each
144.2485 +     * of the six boolean comparison operators ({@literal <}, ==,
144.2486 +     * {@literal >}, {@literal >=}, !=, {@literal <=}).  The suggested
144.2487 +     * idiom for performing these comparisons is: {@code
144.2488 +     * (x.compareTo(y)} &lt;<i>op</i>&gt; {@code 0)}, where
144.2489 +     * &lt;<i>op</i>&gt; is one of the six comparison operators.
144.2490 +     *
144.2491 +     * @param  val BigInteger to which this BigInteger is to be compared.
144.2492 +     * @return -1, 0 or 1 as this BigInteger is numerically less than, equal
144.2493 +     *         to, or greater than {@code val}.
144.2494 +     */
144.2495 +    public int compareTo(BigInteger val) {
144.2496 +        if (signum == val.signum) {
144.2497 +            switch (signum) {
144.2498 +            case 1:
144.2499 +                return compareMagnitude(val);
144.2500 +            case -1:
144.2501 +                return val.compareMagnitude(this);
144.2502 +            default:
144.2503 +                return 0;
144.2504 +            }
144.2505 +        }
144.2506 +        return signum > val.signum ? 1 : -1;
144.2507 +    }
144.2508 +
144.2509 +    /**
144.2510 +     * Compares the magnitude array of this BigInteger with the specified
144.2511 +     * BigInteger's. This is the version of compareTo ignoring sign.
144.2512 +     *
144.2513 +     * @param val BigInteger whose magnitude array to be compared.
144.2514 +     * @return -1, 0 or 1 as this magnitude array is less than, equal to or
144.2515 +     *         greater than the magnitude aray for the specified BigInteger's.
144.2516 +     */
144.2517 +    final int compareMagnitude(BigInteger val) {
144.2518 +        int[] m1 = mag;
144.2519 +        int len1 = m1.length;
144.2520 +        int[] m2 = val.mag;
144.2521 +        int len2 = m2.length;
144.2522 +        if (len1 < len2)
144.2523 +            return -1;
144.2524 +        if (len1 > len2)
144.2525 +            return 1;
144.2526 +        for (int i = 0; i < len1; i++) {
144.2527 +            int a = m1[i];
144.2528 +            int b = m2[i];
144.2529 +            if (a != b)
144.2530 +                return ((a & LONG_MASK) < (b & LONG_MASK)) ? -1 : 1;
144.2531 +        }
144.2532 +        return 0;
144.2533 +    }
144.2534 +
144.2535 +    /**
144.2536 +     * Compares this BigInteger with the specified Object for equality.
144.2537 +     *
144.2538 +     * @param  x Object to which this BigInteger is to be compared.
144.2539 +     * @return {@code true} if and only if the specified Object is a
144.2540 +     *         BigInteger whose value is numerically equal to this BigInteger.
144.2541 +     */
144.2542 +    public boolean equals(Object x) {
144.2543 +        // This test is just an optimization, which may or may not help
144.2544 +        if (x == this)
144.2545 +            return true;
144.2546 +
144.2547 +        if (!(x instanceof BigInteger))
144.2548 +            return false;
144.2549 +
144.2550 +        BigInteger xInt = (BigInteger) x;
144.2551 +        if (xInt.signum != signum)
144.2552 +            return false;
144.2553 +
144.2554 +        int[] m = mag;
144.2555 +        int len = m.length;
144.2556 +        int[] xm = xInt.mag;
144.2557 +        if (len != xm.length)
144.2558 +            return false;
144.2559 +
144.2560 +        for (int i = 0; i < len; i++)
144.2561 +            if (xm[i] != m[i])
144.2562 +                return false;
144.2563 +
144.2564 +        return true;
144.2565 +    }
144.2566 +
144.2567 +    /**
144.2568 +     * Returns the minimum of this BigInteger and {@code val}.
144.2569 +     *
144.2570 +     * @param  val value with which the minimum is to be computed.
144.2571 +     * @return the BigInteger whose value is the lesser of this BigInteger and
144.2572 +     *         {@code val}.  If they are equal, either may be returned.
144.2573 +     */
144.2574 +    public BigInteger min(BigInteger val) {
144.2575 +        return (compareTo(val)<0 ? this : val);
144.2576 +    }
144.2577 +
144.2578 +    /**
144.2579 +     * Returns the maximum of this BigInteger and {@code val}.
144.2580 +     *
144.2581 +     * @param  val value with which the maximum is to be computed.
144.2582 +     * @return the BigInteger whose value is the greater of this and
144.2583 +     *         {@code val}.  If they are equal, either may be returned.
144.2584 +     */
144.2585 +    public BigInteger max(BigInteger val) {
144.2586 +        return (compareTo(val)>0 ? this : val);
144.2587 +    }
144.2588 +
144.2589 +
144.2590 +    // Hash Function
144.2591 +
144.2592 +    /**
144.2593 +     * Returns the hash code for this BigInteger.
144.2594 +     *
144.2595 +     * @return hash code for this BigInteger.
144.2596 +     */
144.2597 +    public int hashCode() {
144.2598 +        int hashCode = 0;
144.2599 +
144.2600 +        for (int i=0; i<mag.length; i++)
144.2601 +            hashCode = (int)(31*hashCode + (mag[i] & LONG_MASK));
144.2602 +
144.2603 +        return hashCode * signum;
144.2604 +    }
144.2605 +
144.2606 +    /**
144.2607 +     * Returns the String representation of this BigInteger in the
144.2608 +     * given radix.  If the radix is outside the range from {@link
144.2609 +     * Character#MIN_RADIX} to {@link Character#MAX_RADIX} inclusive,
144.2610 +     * it will default to 10 (as is the case for
144.2611 +     * {@code Integer.toString}).  The digit-to-character mapping
144.2612 +     * provided by {@code Character.forDigit} is used, and a minus
144.2613 +     * sign is prepended if appropriate.  (This representation is
144.2614 +     * compatible with the {@link #BigInteger(String, int) (String,
144.2615 +     * int)} constructor.)
144.2616 +     *
144.2617 +     * @param  radix  radix of the String representation.
144.2618 +     * @return String representation of this BigInteger in the given radix.
144.2619 +     * @see    Integer#toString
144.2620 +     * @see    Character#forDigit
144.2621 +     * @see    #BigInteger(java.lang.String, int)
144.2622 +     */
144.2623 +    public String toString(int radix) {
144.2624 +        if (signum == 0)
144.2625 +            return "0";
144.2626 +        if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
144.2627 +            radix = 10;
144.2628 +
144.2629 +        // Compute upper bound on number of digit groups and allocate space
144.2630 +        int maxNumDigitGroups = (4*mag.length + 6)/7;
144.2631 +        String digitGroup[] = new String[maxNumDigitGroups];
144.2632 +
144.2633 +        // Translate number to string, a digit group at a time
144.2634 +        BigInteger tmp = this.abs();
144.2635 +        int numGroups = 0;
144.2636 +        while (tmp.signum != 0) {
144.2637 +            BigInteger d = longRadix[radix];
144.2638 +
144.2639 +            MutableBigInteger q = new MutableBigInteger(),
144.2640 +                              a = new MutableBigInteger(tmp.mag),
144.2641 +                              b = new MutableBigInteger(d.mag);
144.2642 +            MutableBigInteger r = a.divide(b, q);
144.2643 +            BigInteger q2 = q.toBigInteger(tmp.signum * d.signum);
144.2644 +            BigInteger r2 = r.toBigInteger(tmp.signum * d.signum);
144.2645 +
144.2646 +            digitGroup[numGroups++] = Long.toString(r2.longValue(), radix);
144.2647 +            tmp = q2;
144.2648 +        }
144.2649 +
144.2650 +        // Put sign (if any) and first digit group into result buffer
144.2651 +        StringBuilder buf = new StringBuilder(numGroups*digitsPerLong[radix]+1);
144.2652 +        if (signum<0)
144.2653 +            buf.append('-');
144.2654 +        buf.append(digitGroup[numGroups-1]);
144.2655 +
144.2656 +        // Append remaining digit groups padded with leading zeros
144.2657 +        for (int i=numGroups-2; i>=0; i--) {
144.2658 +            // Prepend (any) leading zeros for this digit group
144.2659 +            int numLeadingZeros = digitsPerLong[radix]-digitGroup[i].length();
144.2660 +            if (numLeadingZeros != 0)
144.2661 +                buf.append(zeros[numLeadingZeros]);
144.2662 +            buf.append(digitGroup[i]);
144.2663 +        }
144.2664 +        return buf.toString();
144.2665 +    }
144.2666 +
144.2667 +    /* zero[i] is a string of i consecutive zeros. */
144.2668 +    private static String zeros[] = new String[64];
144.2669 +    static {
144.2670 +        zeros[63] =
144.2671 +            "000000000000000000000000000000000000000000000000000000000000000";
144.2672 +        for (int i=0; i<63; i++)
144.2673 +            zeros[i] = zeros[63].substring(0, i);
144.2674 +    }
144.2675 +
144.2676 +    /**
144.2677 +     * Returns the decimal String representation of this BigInteger.
144.2678 +     * The digit-to-character mapping provided by
144.2679 +     * {@code Character.forDigit} is used, and a minus sign is
144.2680 +     * prepended if appropriate.  (This representation is compatible
144.2681 +     * with the {@link #BigInteger(String) (String)} constructor, and
144.2682 +     * allows for String concatenation with Java's + operator.)
144.2683 +     *
144.2684 +     * @return decimal String representation of this BigInteger.
144.2685 +     * @see    Character#forDigit
144.2686 +     * @see    #BigInteger(java.lang.String)
144.2687 +     */
144.2688 +    public String toString() {
144.2689 +        return toString(10);
144.2690 +    }
144.2691 +
144.2692 +    /**
144.2693 +     * Returns a byte array containing the two's-complement
144.2694 +     * representation of this BigInteger.  The byte array will be in
144.2695 +     * <i>big-endian</i> byte-order: the most significant byte is in
144.2696 +     * the zeroth element.  The array will contain the minimum number
144.2697 +     * of bytes required to represent this BigInteger, including at
144.2698 +     * least one sign bit, which is {@code (ceil((this.bitLength() +
144.2699 +     * 1)/8))}.  (This representation is compatible with the
144.2700 +     * {@link #BigInteger(byte[]) (byte[])} constructor.)
144.2701 +     *
144.2702 +     * @return a byte array containing the two's-complement representation of
144.2703 +     *         this BigInteger.
144.2704 +     * @see    #BigInteger(byte[])
144.2705 +     */
144.2706 +    public byte[] toByteArray() {
144.2707 +        int byteLen = bitLength()/8 + 1;
144.2708 +        byte[] byteArray = new byte[byteLen];
144.2709 +
144.2710 +        for (int i=byteLen-1, bytesCopied=4, nextInt=0, intIndex=0; i>=0; i--) {
144.2711 +            if (bytesCopied == 4) {
144.2712 +                nextInt = getInt(intIndex++);
144.2713 +                bytesCopied = 1;
144.2714 +            } else {
144.2715 +                nextInt >>>= 8;
144.2716 +                bytesCopied++;
144.2717 +            }
144.2718 +            byteArray[i] = (byte)nextInt;
144.2719 +        }
144.2720 +        return byteArray;
144.2721 +    }
144.2722 +
144.2723 +    /**
144.2724 +     * Converts this BigInteger to an {@code int}.  This
144.2725 +     * conversion is analogous to a
144.2726 +     * <i>narrowing primitive conversion</i> from {@code long} to
144.2727 +     * {@code int} as defined in section 5.1.3 of
144.2728 +     * <cite>The Java&trade; Language Specification</cite>:
144.2729 +     * if this BigInteger is too big to fit in an
144.2730 +     * {@code int}, only the low-order 32 bits are returned.
144.2731 +     * Note that this conversion can lose information about the
144.2732 +     * overall magnitude of the BigInteger value as well as return a
144.2733 +     * result with the opposite sign.
144.2734 +     *
144.2735 +     * @return this BigInteger converted to an {@code int}.
144.2736 +     */
144.2737 +    public int intValue() {
144.2738 +        int result = 0;
144.2739 +        result = getInt(0);
144.2740 +        return result;
144.2741 +    }
144.2742 +
144.2743 +    /**
144.2744 +     * Converts this BigInteger to a {@code long}.  This
144.2745 +     * conversion is analogous to a
144.2746 +     * <i>narrowing primitive conversion</i> from {@code long} to
144.2747 +     * {@code int} as defined in section 5.1.3 of
144.2748 +     * <cite>The Java&trade; Language Specification</cite>:
144.2749 +     * if this BigInteger is too big to fit in a
144.2750 +     * {@code long}, only the low-order 64 bits are returned.
144.2751 +     * Note that this conversion can lose information about the
144.2752 +     * overall magnitude of the BigInteger value as well as return a
144.2753 +     * result with the opposite sign.
144.2754 +     *
144.2755 +     * @return this BigInteger converted to a {@code long}.
144.2756 +     */
144.2757 +    public long longValue() {
144.2758 +        long result = 0;
144.2759 +
144.2760 +        for (int i=1; i>=0; i--)
144.2761 +            result = (result << 32) + (getInt(i) & LONG_MASK);
144.2762 +        return result;
144.2763 +    }
144.2764 +
144.2765 +    /**
144.2766 +     * Converts this BigInteger to a {@code float}.  This
144.2767 +     * conversion is similar to the
144.2768 +     * <i>narrowing primitive conversion</i> from {@code double} to
144.2769 +     * {@code float} as defined in section 5.1.3 of
144.2770 +     * <cite>The Java&trade; Language Specification</cite>:
144.2771 +     * if this BigInteger has too great a magnitude
144.2772 +     * to represent as a {@code float}, it will be converted to
144.2773 +     * {@link Float#NEGATIVE_INFINITY} or {@link
144.2774 +     * Float#POSITIVE_INFINITY} as appropriate.  Note that even when
144.2775 +     * the return value is finite, this conversion can lose
144.2776 +     * information about the precision of the BigInteger value.
144.2777 +     *
144.2778 +     * @return this BigInteger converted to a {@code float}.
144.2779 +     */
144.2780 +    public float floatValue() {
144.2781 +        // Somewhat inefficient, but guaranteed to work.
144.2782 +        return Float.parseFloat(this.toString());
144.2783 +    }
144.2784 +
144.2785 +    /**
144.2786 +     * Converts this BigInteger to a {@code double}.  This
144.2787 +     * conversion is similar to the
144.2788 +     * <i>narrowing primitive conversion</i> from {@code double} to
144.2789 +     * {@code float} as defined in section 5.1.3 of
144.2790 +     * <cite>The Java&trade; Language Specification</cite>:
144.2791 +     * if this BigInteger has too great a magnitude
144.2792 +     * to represent as a {@code double}, it will be converted to
144.2793 +     * {@link Double#NEGATIVE_INFINITY} or {@link
144.2794 +     * Double#POSITIVE_INFINITY} as appropriate.  Note that even when
144.2795 +     * the return value is finite, this conversion can lose
144.2796 +     * information about the precision of the BigInteger value.
144.2797 +     *
144.2798 +     * @return this BigInteger converted to a {@code double}.
144.2799 +     */
144.2800 +    public double doubleValue() {
144.2801 +        // Somewhat inefficient, but guaranteed to work.
144.2802 +        return Double.parseDouble(this.toString());
144.2803 +    }
144.2804 +
144.2805 +    /**
144.2806 +     * Returns a copy of the input array stripped of any leading zero bytes.
144.2807 +     */
144.2808 +    private static int[] stripLeadingZeroInts(int val[]) {
144.2809 +        int vlen = val.length;
144.2810 +        int keep;
144.2811 +
144.2812 +        // Find first nonzero byte
144.2813 +        for (keep = 0; keep < vlen && val[keep] == 0; keep++)
144.2814 +            ;
144.2815 +        return java.util.Arrays.copyOfRange(val, keep, vlen);
144.2816 +    }
144.2817 +
144.2818 +    /**
144.2819 +     * Returns the input array stripped of any leading zero bytes.
144.2820 +     * Since the source is trusted the copying may be skipped.
144.2821 +     */
144.2822 +    private static int[] trustedStripLeadingZeroInts(int val[]) {
144.2823 +        int vlen = val.length;
144.2824 +        int keep;
144.2825 +
144.2826 +        // Find first nonzero byte
144.2827 +        for (keep = 0; keep < vlen && val[keep] == 0; keep++)
144.2828 +            ;
144.2829 +        return keep == 0 ? val : java.util.Arrays.copyOfRange(val, keep, vlen);
144.2830 +    }
144.2831 +
144.2832 +    /**
144.2833 +     * Returns a copy of the input array stripped of any leading zero bytes.
144.2834 +     */
144.2835 +    private static int[] stripLeadingZeroBytes(byte a[]) {
144.2836 +        int byteLength = a.length;
144.2837 +        int keep;
144.2838 +
144.2839 +        // Find first nonzero byte
144.2840 +        for (keep = 0; keep < byteLength && a[keep]==0; keep++)
144.2841 +            ;
144.2842 +
144.2843 +        // Allocate new array and copy relevant part of input array
144.2844 +        int intLength = ((byteLength - keep) + 3) >>> 2;
144.2845 +        int[] result = new int[intLength];
144.2846 +        int b = byteLength - 1;
144.2847 +        for (int i = intLength-1; i >= 0; i--) {
144.2848 +            result[i] = a[b--] & 0xff;
144.2849 +            int bytesRemaining = b - keep + 1;
144.2850 +            int bytesToTransfer = Math.min(3, bytesRemaining);
144.2851 +            for (int j=8; j <= (bytesToTransfer << 3); j += 8)
144.2852 +                result[i] |= ((a[b--] & 0xff) << j);
144.2853 +        }
144.2854 +        return result;
144.2855 +    }
144.2856 +
144.2857 +    /**
144.2858 +     * Takes an array a representing a negative 2's-complement number and
144.2859 +     * returns the minimal (no leading zero bytes) unsigned whose value is -a.
144.2860 +     */
144.2861 +    private static int[] makePositive(byte a[]) {
144.2862 +        int keep, k;
144.2863 +        int byteLength = a.length;
144.2864 +
144.2865 +        // Find first non-sign (0xff) byte of input
144.2866 +        for (keep=0; keep<byteLength && a[keep]==-1; keep++)
144.2867 +            ;
144.2868 +
144.2869 +
144.2870 +        /* Allocate output array.  If all non-sign bytes are 0x00, we must
144.2871 +         * allocate space for one extra output byte. */
144.2872 +        for (k=keep; k<byteLength && a[k]==0; k++)
144.2873 +            ;
144.2874 +
144.2875 +        int extraByte = (k==byteLength) ? 1 : 0;
144.2876 +        int intLength = ((byteLength - keep + extraByte) + 3)/4;
144.2877 +        int result[] = new int[intLength];
144.2878 +
144.2879 +        /* Copy one's complement of input into output, leaving extra
144.2880 +         * byte (if it exists) == 0x00 */
144.2881 +        int b = byteLength - 1;
144.2882 +        for (int i = intLength-1; i >= 0; i--) {
144.2883 +            result[i] = a[b--] & 0xff;
144.2884 +            int numBytesToTransfer = Math.min(3, b-keep+1);
144.2885 +            if (numBytesToTransfer < 0)
144.2886 +                numBytesToTransfer = 0;
144.2887 +            for (int j=8; j <= 8*numBytesToTransfer; j += 8)
144.2888 +                result[i] |= ((a[b--] & 0xff) << j);
144.2889 +
144.2890 +            // Mask indicates which bits must be complemented
144.2891 +            int mask = -1 >>> (8*(3-numBytesToTransfer));
144.2892 +            result[i] = ~result[i] & mask;
144.2893 +        }
144.2894 +
144.2895 +        // Add one to one's complement to generate two's complement
144.2896 +        for (int i=result.length-1; i>=0; i--) {
144.2897 +            result[i] = (int)((result[i] & LONG_MASK) + 1);
144.2898 +            if (result[i] != 0)
144.2899 +                break;
144.2900 +        }
144.2901 +
144.2902 +        return result;
144.2903 +    }
144.2904 +
144.2905 +    /**
144.2906 +     * Takes an array a representing a negative 2's-complement number and
144.2907 +     * returns the minimal (no leading zero ints) unsigned whose value is -a.
144.2908 +     */
144.2909 +    private static int[] makePositive(int a[]) {
144.2910 +        int keep, j;
144.2911 +
144.2912 +        // Find first non-sign (0xffffffff) int of input
144.2913 +        for (keep=0; keep<a.length && a[keep]==-1; keep++)
144.2914 +            ;
144.2915 +
144.2916 +        /* Allocate output array.  If all non-sign ints are 0x00, we must
144.2917 +         * allocate space for one extra output int. */
144.2918 +        for (j=keep; j<a.length && a[j]==0; j++)
144.2919 +            ;
144.2920 +        int extraInt = (j==a.length ? 1 : 0);
144.2921 +        int result[] = new int[a.length - keep + extraInt];
144.2922 +
144.2923 +        /* Copy one's complement of input into output, leaving extra
144.2924 +         * int (if it exists) == 0x00 */
144.2925 +        for (int i = keep; i<a.length; i++)
144.2926 +            result[i - keep + extraInt] = ~a[i];
144.2927 +
144.2928 +        // Add one to one's complement to generate two's complement
144.2929 +        for (int i=result.length-1; ++result[i]==0; i--)
144.2930 +            ;
144.2931 +
144.2932 +        return result;
144.2933 +    }
144.2934 +
144.2935 +    /*
144.2936 +     * The following two arrays are used for fast String conversions.  Both
144.2937 +     * are indexed by radix.  The first is the number of digits of the given
144.2938 +     * radix that can fit in a Java long without "going negative", i.e., the
144.2939 +     * highest integer n such that radix**n < 2**63.  The second is the
144.2940 +     * "long radix" that tears each number into "long digits", each of which
144.2941 +     * consists of the number of digits in the corresponding element in
144.2942 +     * digitsPerLong (longRadix[i] = i**digitPerLong[i]).  Both arrays have
144.2943 +     * nonsense values in their 0 and 1 elements, as radixes 0 and 1 are not
144.2944 +     * used.
144.2945 +     */
144.2946 +    private static int digitsPerLong[] = {0, 0,
144.2947 +        62, 39, 31, 27, 24, 22, 20, 19, 18, 18, 17, 17, 16, 16, 15, 15, 15, 14,
144.2948 +        14, 14, 14, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12};
144.2949 +
144.2950 +    private static BigInteger longRadix[] = {null, null,
144.2951 +        valueOf(0x4000000000000000L), valueOf(0x383d9170b85ff80bL),
144.2952 +        valueOf(0x4000000000000000L), valueOf(0x6765c793fa10079dL),
144.2953 +        valueOf(0x41c21cb8e1000000L), valueOf(0x3642798750226111L),
144.2954 +        valueOf(0x1000000000000000L), valueOf(0x12bf307ae81ffd59L),
144.2955 +        valueOf( 0xde0b6b3a7640000L), valueOf(0x4d28cb56c33fa539L),
144.2956 +        valueOf(0x1eca170c00000000L), valueOf(0x780c7372621bd74dL),
144.2957 +        valueOf(0x1e39a5057d810000L), valueOf(0x5b27ac993df97701L),
144.2958 +        valueOf(0x1000000000000000L), valueOf(0x27b95e997e21d9f1L),
144.2959 +        valueOf(0x5da0e1e53c5c8000L), valueOf( 0xb16a458ef403f19L),
144.2960 +        valueOf(0x16bcc41e90000000L), valueOf(0x2d04b7fdd9c0ef49L),
144.2961 +        valueOf(0x5658597bcaa24000L), valueOf( 0x6feb266931a75b7L),
144.2962 +        valueOf( 0xc29e98000000000L), valueOf(0x14adf4b7320334b9L),
144.2963 +        valueOf(0x226ed36478bfa000L), valueOf(0x383d9170b85ff80bL),
144.2964 +        valueOf(0x5a3c23e39c000000L), valueOf( 0x4e900abb53e6b71L),
144.2965 +        valueOf( 0x7600ec618141000L), valueOf( 0xaee5720ee830681L),
144.2966 +        valueOf(0x1000000000000000L), valueOf(0x172588ad4f5f0981L),
144.2967 +        valueOf(0x211e44f7d02c1000L), valueOf(0x2ee56725f06e5c71L),
144.2968 +        valueOf(0x41c21cb8e1000000L)};
144.2969 +
144.2970 +    /*
144.2971 +     * These two arrays are the integer analogue of above.
144.2972 +     */
144.2973 +    private static int digitsPerInt[] = {0, 0, 30, 19, 15, 13, 11,
144.2974 +        11, 10, 9, 9, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
144.2975 +        6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5};
144.2976 +
144.2977 +    private static int intRadix[] = {0, 0,
144.2978 +        0x40000000, 0x4546b3db, 0x40000000, 0x48c27395, 0x159fd800,
144.2979 +        0x75db9c97, 0x40000000, 0x17179149, 0x3b9aca00, 0xcc6db61,
144.2980 +        0x19a10000, 0x309f1021, 0x57f6c100, 0xa2f1b6f,  0x10000000,
144.2981 +        0x18754571, 0x247dbc80, 0x3547667b, 0x4c4b4000, 0x6b5a6e1d,
144.2982 +        0x6c20a40,  0x8d2d931,  0xb640000,  0xe8d4a51,  0x1269ae40,
144.2983 +        0x17179149, 0x1cb91000, 0x23744899, 0x2b73a840, 0x34e63b41,
144.2984 +        0x40000000, 0x4cfa3cc1, 0x5c13d840, 0x6d91b519, 0x39aa400
144.2985 +    };
144.2986 +
144.2987 +    /**
144.2988 +     * These routines provide access to the two's complement representation
144.2989 +     * of BigIntegers.
144.2990 +     */
144.2991 +
144.2992 +    /**
144.2993 +     * Returns the length of the two's complement representation in ints,
144.2994 +     * including space for at least one sign bit.
144.2995 +     */
144.2996 +    private int intLength() {
144.2997 +        return (bitLength() >>> 5) + 1;
144.2998 +    }
144.2999 +
144.3000 +    /* Returns sign bit */
144.3001 +    private int signBit() {
144.3002 +        return signum < 0 ? 1 : 0;
144.3003 +    }
144.3004 +
144.3005 +    /* Returns an int of sign bits */
144.3006 +    private int signInt() {
144.3007 +        return signum < 0 ? -1 : 0;
144.3008 +    }
144.3009 +
144.3010 +    /**
144.3011 +     * Returns the specified int of the little-endian two's complement
144.3012 +     * representation (int 0 is the least significant).  The int number can
144.3013 +     * be arbitrarily high (values are logically preceded by infinitely many
144.3014 +     * sign ints).
144.3015 +     */
144.3016 +    private int getInt(int n) {
144.3017 +        if (n < 0)
144.3018 +            return 0;
144.3019 +        if (n >= mag.length)
144.3020 +            return signInt();
144.3021 +
144.3022 +        int magInt = mag[mag.length-n-1];
144.3023 +
144.3024 +        return (signum >= 0 ? magInt :
144.3025 +                (n <= firstNonzeroIntNum() ? -magInt : ~magInt));
144.3026 +    }
144.3027 +
144.3028 +    /**
144.3029 +     * Returns the index of the int that contains the first nonzero int in the
144.3030 +     * little-endian binary representation of the magnitude (int 0 is the
144.3031 +     * least significant). If the magnitude is zero, return value is undefined.
144.3032 +     */
144.3033 +     private int firstNonzeroIntNum() {
144.3034 +         int fn = firstNonzeroIntNum - 2;
144.3035 +         if (fn == -2) { // firstNonzeroIntNum not initialized yet
144.3036 +             fn = 0;
144.3037 +
144.3038 +             // Search for the first nonzero int
144.3039 +             int i;
144.3040 +             int mlen = mag.length;
144.3041 +             for (i = mlen - 1; i >= 0 && mag[i] == 0; i--)
144.3042 +                 ;
144.3043 +             fn = mlen - i - 1;
144.3044 +             firstNonzeroIntNum = fn + 2; // offset by two to initialize
144.3045 +         }
144.3046 +         return fn;
144.3047 +     }
144.3048 +
144.3049 +    /** use serialVersionUID from JDK 1.1. for interoperability */
144.3050 +    private static final long serialVersionUID = -8287574255936472291L;
144.3051 +
144.3052 +    /**
144.3053 +     * Serializable fields for BigInteger.
144.3054 +     *
144.3055 +     * @serialField signum  int
144.3056 +     *              signum of this BigInteger.
144.3057 +     * @serialField magnitude int[]
144.3058 +     *              magnitude array of this BigInteger.
144.3059 +     * @serialField bitCount  int
144.3060 +     *              number of bits in this BigInteger
144.3061 +     * @serialField bitLength int
144.3062 +     *              the number of bits in the minimal two's-complement
144.3063 +     *              representation of this BigInteger
144.3064 +     * @serialField lowestSetBit int
144.3065 +     *              lowest set bit in the twos complement representation
144.3066 +     */
144.3067 +    private static final ObjectStreamField[] serialPersistentFields = {
144.3068 +        new ObjectStreamField("signum", Integer.TYPE),
144.3069 +        new ObjectStreamField("magnitude", byte[].class),
144.3070 +        new ObjectStreamField("bitCount", Integer.TYPE),
144.3071 +        new ObjectStreamField("bitLength", Integer.TYPE),
144.3072 +        new ObjectStreamField("firstNonzeroByteNum", Integer.TYPE),
144.3073 +        new ObjectStreamField("lowestSetBit", Integer.TYPE)
144.3074 +        };
144.3075 +
144.3076 +
144.3077 +
144.3078 +    /**
144.3079 +     * Save the {@code BigInteger} instance to a stream.
144.3080 +     * The magnitude of a BigInteger is serialized as a byte array for
144.3081 +     * historical reasons.
144.3082 +     *
144.3083 +     * @serialData two necessary fields are written as well as obsolete
144.3084 +     *             fields for compatibility with older versions.
144.3085 +     */
144.3086 +    private void writeObject(ObjectOutputStream s) throws IOException {
144.3087 +        // set the values of the Serializable fields
144.3088 +        ObjectOutputStream.PutField fields = s.putFields();
144.3089 +        fields.put("signum", signum);
144.3090 +        fields.put("magnitude", magSerializedForm());
144.3091 +        // The values written for cached fields are compatible with older
144.3092 +        // versions, but are ignored in readObject so don't otherwise matter.
144.3093 +        fields.put("bitCount", -1);
144.3094 +        fields.put("bitLength", -1);
144.3095 +        fields.put("lowestSetBit", -2);
144.3096 +        fields.put("firstNonzeroByteNum", -2);
144.3097 +
144.3098 +        // save them
144.3099 +        s.writeFields();
144.3100 +}
144.3101 +
144.3102 +    /**
144.3103 +     * Returns the mag array as an array of bytes.
144.3104 +     */
144.3105 +    private byte[] magSerializedForm() {
144.3106 +        int len = mag.length;
144.3107 +
144.3108 +        int bitLen = (len == 0 ? 0 : ((len - 1) << 5) + bitLengthForInt(mag[0]));
144.3109 +        int byteLen = (bitLen + 7) >>> 3;
144.3110 +        byte[] result = new byte[byteLen];
144.3111 +
144.3112 +        for (int i = byteLen - 1, bytesCopied = 4, intIndex = len - 1, nextInt = 0;
144.3113 +             i>=0; i--) {
144.3114 +            if (bytesCopied == 4) {
144.3115 +                nextInt = mag[intIndex--];
144.3116 +                bytesCopied = 1;
144.3117 +            } else {
144.3118 +                nextInt >>>= 8;
144.3119 +                bytesCopied++;
144.3120 +            }
144.3121 +            result[i] = (byte)nextInt;
144.3122 +        }
144.3123 +        return result;
144.3124 +    }
144.3125 +}
   145.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   145.2 +++ b/rt/emul/compact/src/main/java/java/math/BitSieve.java	Mon Oct 07 14:20:58 2013 +0200
   145.3 @@ -0,0 +1,212 @@
   145.4 +/*
   145.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   145.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   145.7 + *
   145.8 + * This code is free software; you can redistribute it and/or modify it
   145.9 + * under the terms of the GNU General Public License version 2 only, as
  145.10 + * published by the Free Software Foundation.  Oracle designates this
  145.11 + * particular file as subject to the "Classpath" exception as provided
  145.12 + * by Oracle in the LICENSE file that accompanied this code.
  145.13 + *
  145.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  145.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  145.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  145.17 + * version 2 for more details (a copy is included in the LICENSE file that
  145.18 + * accompanied this code).
  145.19 + *
  145.20 + * You should have received a copy of the GNU General Public License version
  145.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  145.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  145.23 + *
  145.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  145.25 + * or visit www.oracle.com if you need additional information or have any
  145.26 + * questions.
  145.27 + */
  145.28 +
  145.29 +package java.math;
  145.30 +
  145.31 +/**
  145.32 + * A simple bit sieve used for finding prime number candidates. Allows setting
  145.33 + * and clearing of bits in a storage array. The size of the sieve is assumed to
  145.34 + * be constant to reduce overhead. All the bits of a new bitSieve are zero, and
  145.35 + * bits are removed from it by setting them.
  145.36 + *
  145.37 + * To reduce storage space and increase efficiency, no even numbers are
  145.38 + * represented in the sieve (each bit in the sieve represents an odd number).
  145.39 + * The relationship between the index of a bit and the number it represents is
  145.40 + * given by
  145.41 + * N = offset + (2*index + 1);
  145.42 + * Where N is the integer represented by a bit in the sieve, offset is some
  145.43 + * even integer offset indicating where the sieve begins, and index is the
  145.44 + * index of a bit in the sieve array.
  145.45 + *
  145.46 + * @see     BigInteger
  145.47 + * @author  Michael McCloskey
  145.48 + * @since   1.3
  145.49 + */
  145.50 +class BitSieve {
  145.51 +    /**
  145.52 +     * Stores the bits in this bitSieve.
  145.53 +     */
  145.54 +    private long bits[];
  145.55 +
  145.56 +    /**
  145.57 +     * Length is how many bits this sieve holds.
  145.58 +     */
  145.59 +    private int length;
  145.60 +
  145.61 +    /**
  145.62 +     * A small sieve used to filter out multiples of small primes in a search
  145.63 +     * sieve.
  145.64 +     */
  145.65 +    private static BitSieve smallSieve = new BitSieve();
  145.66 +
  145.67 +    /**
  145.68 +     * Construct a "small sieve" with a base of 0.  This constructor is
  145.69 +     * used internally to generate the set of "small primes" whose multiples
  145.70 +     * are excluded from sieves generated by the main (package private)
  145.71 +     * constructor, BitSieve(BigInteger base, int searchLen).  The length
  145.72 +     * of the sieve generated by this constructor was chosen for performance;
  145.73 +     * it controls a tradeoff between how much time is spent constructing
  145.74 +     * other sieves, and how much time is wasted testing composite candidates
  145.75 +     * for primality.  The length was chosen experimentally to yield good
  145.76 +     * performance.
  145.77 +     */
  145.78 +    private BitSieve() {
  145.79 +        length = 150 * 64;
  145.80 +        bits = new long[(unitIndex(length - 1) + 1)];
  145.81 +
  145.82 +        // Mark 1 as composite
  145.83 +        set(0);
  145.84 +        int nextIndex = 1;
  145.85 +        int nextPrime = 3;
  145.86 +
  145.87 +        // Find primes and remove their multiples from sieve
  145.88 +        do {
  145.89 +            sieveSingle(length, nextIndex + nextPrime, nextPrime);
  145.90 +            nextIndex = sieveSearch(length, nextIndex + 1);
  145.91 +            nextPrime = 2*nextIndex + 1;
  145.92 +        } while((nextIndex > 0) && (nextPrime < length));
  145.93 +    }
  145.94 +
  145.95 +    /**
  145.96 +     * Construct a bit sieve of searchLen bits used for finding prime number
  145.97 +     * candidates. The new sieve begins at the specified base, which must
  145.98 +     * be even.
  145.99 +     */
 145.100 +    BitSieve(BigInteger base, int searchLen) {
 145.101 +        /*
 145.102 +         * Candidates are indicated by clear bits in the sieve. As a candidates
 145.103 +         * nonprimality is calculated, a bit is set in the sieve to eliminate
 145.104 +         * it. To reduce storage space and increase efficiency, no even numbers
 145.105 +         * are represented in the sieve (each bit in the sieve represents an
 145.106 +         * odd number).
 145.107 +         */
 145.108 +        bits = new long[(unitIndex(searchLen-1) + 1)];
 145.109 +        length = searchLen;
 145.110 +        int start = 0;
 145.111 +
 145.112 +        int step = smallSieve.sieveSearch(smallSieve.length, start);
 145.113 +        int convertedStep = (step *2) + 1;
 145.114 +
 145.115 +        // Construct the large sieve at an even offset specified by base
 145.116 +        MutableBigInteger b = new MutableBigInteger(base);
 145.117 +        MutableBigInteger q = new MutableBigInteger();
 145.118 +        do {
 145.119 +            // Calculate base mod convertedStep
 145.120 +            start = b.divideOneWord(convertedStep, q);
 145.121 +
 145.122 +            // Take each multiple of step out of sieve
 145.123 +            start = convertedStep - start;
 145.124 +            if (start%2 == 0)
 145.125 +                start += convertedStep;
 145.126 +            sieveSingle(searchLen, (start-1)/2, convertedStep);
 145.127 +
 145.128 +            // Find next prime from small sieve
 145.129 +            step = smallSieve.sieveSearch(smallSieve.length, step+1);
 145.130 +            convertedStep = (step *2) + 1;
 145.131 +        } while (step > 0);
 145.132 +    }
 145.133 +
 145.134 +    /**
 145.135 +     * Given a bit index return unit index containing it.
 145.136 +     */
 145.137 +    private static int unitIndex(int bitIndex) {
 145.138 +        return bitIndex >>> 6;
 145.139 +    }
 145.140 +
 145.141 +    /**
 145.142 +     * Return a unit that masks the specified bit in its unit.
 145.143 +     */
 145.144 +    private static long bit(int bitIndex) {
 145.145 +        return 1L << (bitIndex & ((1<<6) - 1));
 145.146 +    }
 145.147 +
 145.148 +    /**
 145.149 +     * Get the value of the bit at the specified index.
 145.150 +     */
 145.151 +    private boolean get(int bitIndex) {
 145.152 +        int unitIndex = unitIndex(bitIndex);
 145.153 +        return ((bits[unitIndex] & bit(bitIndex)) != 0);
 145.154 +    }
 145.155 +
 145.156 +    /**
 145.157 +     * Set the bit at the specified index.
 145.158 +     */
 145.159 +    private void set(int bitIndex) {
 145.160 +        int unitIndex = unitIndex(bitIndex);
 145.161 +        bits[unitIndex] |= bit(bitIndex);
 145.162 +    }
 145.163 +
 145.164 +    /**
 145.165 +     * This method returns the index of the first clear bit in the search
 145.166 +     * array that occurs at or after start. It will not search past the
 145.167 +     * specified limit. It returns -1 if there is no such clear bit.
 145.168 +     */
 145.169 +    private int sieveSearch(int limit, int start) {
 145.170 +        if (start >= limit)
 145.171 +            return -1;
 145.172 +
 145.173 +        int index = start;
 145.174 +        do {
 145.175 +            if (!get(index))
 145.176 +                return index;
 145.177 +            index++;
 145.178 +        } while(index < limit-1);
 145.179 +        return -1;
 145.180 +    }
 145.181 +
 145.182 +    /**
 145.183 +     * Sieve a single set of multiples out of the sieve. Begin to remove
 145.184 +     * multiples of the specified step starting at the specified start index,
 145.185 +     * up to the specified limit.
 145.186 +     */
 145.187 +    private void sieveSingle(int limit, int start, int step) {
 145.188 +        while(start < limit) {
 145.189 +            set(start);
 145.190 +            start += step;
 145.191 +        }
 145.192 +    }
 145.193 +
 145.194 +    /**
 145.195 +     * Test probable primes in the sieve and return successful candidates.
 145.196 +     */
 145.197 +    BigInteger retrieve(BigInteger initValue, int certainty, java.util.Random random) {
 145.198 +        // Examine the sieve one long at a time to find possible primes
 145.199 +        int offset = 1;
 145.200 +        for (int i=0; i<bits.length; i++) {
 145.201 +            long nextLong = ~bits[i];
 145.202 +            for (int j=0; j<64; j++) {
 145.203 +                if ((nextLong & 1) == 1) {
 145.204 +                    BigInteger candidate = initValue.add(
 145.205 +                                           BigInteger.valueOf(offset));
 145.206 +                    if (candidate.primeToCertainty(certainty, random))
 145.207 +                        return candidate;
 145.208 +                }
 145.209 +                nextLong >>>= 1;
 145.210 +                offset+=2;
 145.211 +            }
 145.212 +        }
 145.213 +        return null;
 145.214 +    }
 145.215 +}
   146.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   146.2 +++ b/rt/emul/compact/src/main/java/java/math/MathContext.java	Mon Oct 07 14:20:58 2013 +0200
   146.3 @@ -0,0 +1,326 @@
   146.4 +/*
   146.5 + * Copyright (c) 2003, 2007, Oracle and/or its affiliates. All rights reserved.
   146.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   146.7 + *
   146.8 + * This code is free software; you can redistribute it and/or modify it
   146.9 + * under the terms of the GNU General Public License version 2 only, as
  146.10 + * published by the Free Software Foundation.  Oracle designates this
  146.11 + * particular file as subject to the "Classpath" exception as provided
  146.12 + * by Oracle in the LICENSE file that accompanied this code.
  146.13 + *
  146.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  146.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  146.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  146.17 + * version 2 for more details (a copy is included in the LICENSE file that
  146.18 + * accompanied this code).
  146.19 + *
  146.20 + * You should have received a copy of the GNU General Public License version
  146.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  146.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  146.23 + *
  146.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  146.25 + * or visit www.oracle.com if you need additional information or have any
  146.26 + * questions.
  146.27 + */
  146.28 +
  146.29 +/*
  146.30 + * Portions Copyright IBM Corporation, 1997, 2001. All Rights Reserved.
  146.31 + */
  146.32 +
  146.33 +package java.math;
  146.34 +import java.io.*;
  146.35 +
  146.36 +/**
  146.37 + * Immutable objects which encapsulate the context settings which
  146.38 + * describe certain rules for numerical operators, such as those
  146.39 + * implemented by the {@link BigDecimal} class.
  146.40 + *
  146.41 + * <p>The base-independent settings are:
  146.42 + * <ol>
  146.43 + * <li>{@code precision}:
  146.44 + * the number of digits to be used for an operation; results are
  146.45 + * rounded to this precision
  146.46 + *
  146.47 + * <li>{@code roundingMode}:
  146.48 + * a {@link RoundingMode} object which specifies the algorithm to be
  146.49 + * used for rounding.
  146.50 + * </ol>
  146.51 + *
  146.52 + * @see     BigDecimal
  146.53 + * @see     RoundingMode
  146.54 + * @author  Mike Cowlishaw
  146.55 + * @author  Joseph D. Darcy
  146.56 + * @since 1.5
  146.57 + */
  146.58 +
  146.59 +public final class MathContext implements Serializable {
  146.60 +
  146.61 +    /* ----- Constants ----- */
  146.62 +
  146.63 +    // defaults for constructors
  146.64 +    private static final int DEFAULT_DIGITS = 9;
  146.65 +    private static final RoundingMode DEFAULT_ROUNDINGMODE = RoundingMode.HALF_UP;
  146.66 +    // Smallest values for digits (Maximum is Integer.MAX_VALUE)
  146.67 +    private static final int MIN_DIGITS = 0;
  146.68 +
  146.69 +    // Serialization version
  146.70 +    private static final long serialVersionUID = 5579720004786848255L;
  146.71 +
  146.72 +    /* ----- Public Properties ----- */
  146.73 +    /**
  146.74 +     *  A {@code MathContext} object whose settings have the values
  146.75 +     *  required for unlimited precision arithmetic.
  146.76 +     *  The values of the settings are:
  146.77 +     *  <code>
  146.78 +     *  precision=0 roundingMode=HALF_UP
  146.79 +     *  </code>
  146.80 +     */
  146.81 +    public static final MathContext UNLIMITED =
  146.82 +        new MathContext(0, RoundingMode.HALF_UP);
  146.83 +
  146.84 +    /**
  146.85 +     *  A {@code MathContext} object with a precision setting
  146.86 +     *  matching the IEEE 754R Decimal32 format, 7 digits, and a
  146.87 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  146.88 +     *  IEEE 754R default.
  146.89 +     */
  146.90 +    public static final MathContext DECIMAL32 =
  146.91 +        new MathContext(7, RoundingMode.HALF_EVEN);
  146.92 +
  146.93 +    /**
  146.94 +     *  A {@code MathContext} object with a precision setting
  146.95 +     *  matching the IEEE 754R Decimal64 format, 16 digits, and a
  146.96 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
  146.97 +     *  IEEE 754R default.
  146.98 +     */
  146.99 +    public static final MathContext DECIMAL64 =
 146.100 +        new MathContext(16, RoundingMode.HALF_EVEN);
 146.101 +
 146.102 +    /**
 146.103 +     *  A {@code MathContext} object with a precision setting
 146.104 +     *  matching the IEEE 754R Decimal128 format, 34 digits, and a
 146.105 +     *  rounding mode of {@link RoundingMode#HALF_EVEN HALF_EVEN}, the
 146.106 +     *  IEEE 754R default.
 146.107 +     */
 146.108 +    public static final MathContext DECIMAL128 =
 146.109 +        new MathContext(34, RoundingMode.HALF_EVEN);
 146.110 +
 146.111 +    /* ----- Shared Properties ----- */
 146.112 +    /**
 146.113 +     * The number of digits to be used for an operation.  A value of 0
 146.114 +     * indicates that unlimited precision (as many digits as are
 146.115 +     * required) will be used.  Note that leading zeros (in the
 146.116 +     * coefficient of a number) are never significant.
 146.117 +     *
 146.118 +     * <p>{@code precision} will always be non-negative.
 146.119 +     *
 146.120 +     * @serial
 146.121 +     */
 146.122 +    final int precision;
 146.123 +
 146.124 +    /**
 146.125 +     * The rounding algorithm to be used for an operation.
 146.126 +     *
 146.127 +     * @see RoundingMode
 146.128 +     * @serial
 146.129 +     */
 146.130 +    final RoundingMode roundingMode;
 146.131 +
 146.132 +    /* ----- Constructors ----- */
 146.133 +
 146.134 +    /**
 146.135 +     * Constructs a new {@code MathContext} with the specified
 146.136 +     * precision and the {@link RoundingMode#HALF_UP HALF_UP} rounding
 146.137 +     * mode.
 146.138 +     *
 146.139 +     * @param setPrecision The non-negative {@code int} precision setting.
 146.140 +     * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
 146.141 +     *         than zero.
 146.142 +     */
 146.143 +    public MathContext(int setPrecision) {
 146.144 +        this(setPrecision, DEFAULT_ROUNDINGMODE);
 146.145 +        return;
 146.146 +    }
 146.147 +
 146.148 +    /**
 146.149 +     * Constructs a new {@code MathContext} with a specified
 146.150 +     * precision and rounding mode.
 146.151 +     *
 146.152 +     * @param setPrecision The non-negative {@code int} precision setting.
 146.153 +     * @param setRoundingMode The rounding mode to use.
 146.154 +     * @throws IllegalArgumentException if the {@code setPrecision} parameter is less
 146.155 +     *         than zero.
 146.156 +     * @throws NullPointerException if the rounding mode argument is {@code null}
 146.157 +     */
 146.158 +    public MathContext(int setPrecision,
 146.159 +                       RoundingMode setRoundingMode) {
 146.160 +        if (setPrecision < MIN_DIGITS)
 146.161 +            throw new IllegalArgumentException("Digits < 0");
 146.162 +        if (setRoundingMode == null)
 146.163 +            throw new NullPointerException("null RoundingMode");
 146.164 +
 146.165 +        precision = setPrecision;
 146.166 +        roundingMode = setRoundingMode;
 146.167 +        return;
 146.168 +    }
 146.169 +
 146.170 +    /**
 146.171 +     * Constructs a new {@code MathContext} from a string.
 146.172 +     *
 146.173 +     * The string must be in the same format as that produced by the
 146.174 +     * {@link #toString} method.
 146.175 +     *
 146.176 +     * <p>An {@code IllegalArgumentException} is thrown if the precision
 146.177 +     * section of the string is out of range ({@code < 0}) or the string is
 146.178 +     * not in the format created by the {@link #toString} method.
 146.179 +     *
 146.180 +     * @param val The string to be parsed
 146.181 +     * @throws IllegalArgumentException if the precision section is out of range
 146.182 +     * or of incorrect format
 146.183 +     * @throws NullPointerException if the argument is {@code null}
 146.184 +     */
 146.185 +    public MathContext(String val) {
 146.186 +        boolean bad = false;
 146.187 +        int setPrecision;
 146.188 +        if (val == null)
 146.189 +            throw new NullPointerException("null String");
 146.190 +        try { // any error here is a string format problem
 146.191 +            if (!val.startsWith("precision=")) throw new RuntimeException();
 146.192 +            int fence = val.indexOf(' ');    // could be -1
 146.193 +            int off = 10;                     // where value starts
 146.194 +            setPrecision = Integer.parseInt(val.substring(10, fence));
 146.195 +
 146.196 +            if (!val.startsWith("roundingMode=", fence+1))
 146.197 +                throw new RuntimeException();
 146.198 +            off = fence + 1 + 13;
 146.199 +            String str = val.substring(off, val.length());
 146.200 +            roundingMode = RoundingMode.valueOf(str);
 146.201 +        } catch (RuntimeException re) {
 146.202 +            throw new IllegalArgumentException("bad string format");
 146.203 +        }
 146.204 +
 146.205 +        if (setPrecision < MIN_DIGITS)
 146.206 +            throw new IllegalArgumentException("Digits < 0");
 146.207 +        // the other parameters cannot be invalid if we got here
 146.208 +        precision = setPrecision;
 146.209 +    }
 146.210 +
 146.211 +    /**
 146.212 +     * Returns the {@code precision} setting.
 146.213 +     * This value is always non-negative.
 146.214 +     *
 146.215 +     * @return an {@code int} which is the value of the {@code precision}
 146.216 +     *         setting
 146.217 +     */
 146.218 +    public int getPrecision() {
 146.219 +        return precision;
 146.220 +    }
 146.221 +
 146.222 +    /**
 146.223 +     * Returns the roundingMode setting.
 146.224 +     * This will be one of
 146.225 +     * {@link  RoundingMode#CEILING},
 146.226 +     * {@link  RoundingMode#DOWN},
 146.227 +     * {@link  RoundingMode#FLOOR},
 146.228 +     * {@link  RoundingMode#HALF_DOWN},
 146.229 +     * {@link  RoundingMode#HALF_EVEN},
 146.230 +     * {@link  RoundingMode#HALF_UP},
 146.231 +     * {@link  RoundingMode#UNNECESSARY}, or
 146.232 +     * {@link  RoundingMode#UP}.
 146.233 +     *
 146.234 +     * @return a {@code RoundingMode} object which is the value of the
 146.235 +     *         {@code roundingMode} setting
 146.236 +     */
 146.237 +
 146.238 +    public RoundingMode getRoundingMode() {
 146.239 +        return roundingMode;
 146.240 +    }
 146.241 +
 146.242 +    /**
 146.243 +     * Compares this {@code MathContext} with the specified
 146.244 +     * {@code Object} for equality.
 146.245 +     *
 146.246 +     * @param  x {@code Object} to which this {@code MathContext} is to
 146.247 +     *         be compared.
 146.248 +     * @return {@code true} if and only if the specified {@code Object} is
 146.249 +     *         a {@code MathContext} object which has exactly the same
 146.250 +     *         settings as this object
 146.251 +     */
 146.252 +    public boolean equals(Object x){
 146.253 +        MathContext mc;
 146.254 +        if (!(x instanceof MathContext))
 146.255 +            return false;
 146.256 +        mc = (MathContext) x;
 146.257 +        return mc.precision == this.precision
 146.258 +            && mc.roundingMode == this.roundingMode; // no need for .equals()
 146.259 +    }
 146.260 +
 146.261 +    /**
 146.262 +     * Returns the hash code for this {@code MathContext}.
 146.263 +     *
 146.264 +     * @return hash code for this {@code MathContext}
 146.265 +     */
 146.266 +    public int hashCode() {
 146.267 +        return this.precision + roundingMode.hashCode() * 59;
 146.268 +    }
 146.269 +
 146.270 +    /**
 146.271 +     * Returns the string representation of this {@code MathContext}.
 146.272 +     * The {@code String} returned represents the settings of the
 146.273 +     * {@code MathContext} object as two space-delimited words
 146.274 +     * (separated by a single space character, <tt>'&#92;u0020'</tt>,
 146.275 +     * and with no leading or trailing white space), as follows:
 146.276 +     * <ol>
 146.277 +     * <li>
 146.278 +     * The string {@code "precision="}, immediately followed
 146.279 +     * by the value of the precision setting as a numeric string as if
 146.280 +     * generated by the {@link Integer#toString(int) Integer.toString}
 146.281 +     * method.
 146.282 +     *
 146.283 +     * <li>
 146.284 +     * The string {@code "roundingMode="}, immediately
 146.285 +     * followed by the value of the {@code roundingMode} setting as a
 146.286 +     * word.  This word will be the same as the name of the
 146.287 +     * corresponding public constant in the {@link RoundingMode}
 146.288 +     * enum.
 146.289 +     * </ol>
 146.290 +     * <p>
 146.291 +     * For example:
 146.292 +     * <pre>
 146.293 +     * precision=9 roundingMode=HALF_UP
 146.294 +     * </pre>
 146.295 +     *
 146.296 +     * Additional words may be appended to the result of
 146.297 +     * {@code toString} in the future if more properties are added to
 146.298 +     * this class.
 146.299 +     *
 146.300 +     * @return a {@code String} representing the context settings
 146.301 +     */
 146.302 +    public java.lang.String toString() {
 146.303 +        return "precision=" +           precision + " " +
 146.304 +               "roundingMode=" +        roundingMode.toString();
 146.305 +    }
 146.306 +
 146.307 +    // Private methods
 146.308 +
 146.309 +    /**
 146.310 +     * Reconstitute the {@code MathContext} instance from a stream (that is,
 146.311 +     * deserialize it).
 146.312 +     *
 146.313 +     * @param s the stream being read.
 146.314 +     */
 146.315 +    private void readObject(java.io.ObjectInputStream s)
 146.316 +        throws java.io.IOException, ClassNotFoundException {
 146.317 +        s.defaultReadObject();     // read in all fields
 146.318 +        // validate possibly bad fields
 146.319 +        if (precision < MIN_DIGITS) {
 146.320 +            String message = "MathContext: invalid digits in stream";
 146.321 +            throw new java.io.StreamCorruptedException(message);
 146.322 +        }
 146.323 +        if (roundingMode == null) {
 146.324 +            String message = "MathContext: null roundingMode in stream";
 146.325 +            throw new java.io.StreamCorruptedException(message);
 146.326 +        }
 146.327 +    }
 146.328 +
 146.329 +}
   147.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   147.2 +++ b/rt/emul/compact/src/main/java/java/math/MutableBigInteger.java	Mon Oct 07 14:20:58 2013 +0200
   147.3 @@ -0,0 +1,1477 @@
   147.4 +/*
   147.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   147.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   147.7 + *
   147.8 + * This code is free software; you can redistribute it and/or modify it
   147.9 + * under the terms of the GNU General Public License version 2 only, as
  147.10 + * published by the Free Software Foundation.  Oracle designates this
  147.11 + * particular file as subject to the "Classpath" exception as provided
  147.12 + * by Oracle in the LICENSE file that accompanied this code.
  147.13 + *
  147.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  147.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  147.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  147.17 + * version 2 for more details (a copy is included in the LICENSE file that
  147.18 + * accompanied this code).
  147.19 + *
  147.20 + * You should have received a copy of the GNU General Public License version
  147.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  147.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  147.23 + *
  147.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  147.25 + * or visit www.oracle.com if you need additional information or have any
  147.26 + * questions.
  147.27 + */
  147.28 +
  147.29 +package java.math;
  147.30 +
  147.31 +/**
  147.32 + * A class used to represent multiprecision integers that makes efficient
  147.33 + * use of allocated space by allowing a number to occupy only part of
  147.34 + * an array so that the arrays do not have to be reallocated as often.
  147.35 + * When performing an operation with many iterations the array used to
  147.36 + * hold a number is only reallocated when necessary and does not have to
  147.37 + * be the same size as the number it represents. A mutable number allows
  147.38 + * calculations to occur on the same number without having to create
  147.39 + * a new number for every step of the calculation as occurs with
  147.40 + * BigIntegers.
  147.41 + *
  147.42 + * @see     BigInteger
  147.43 + * @author  Michael McCloskey
  147.44 + * @since   1.3
  147.45 + */
  147.46 +
  147.47 +import java.util.Arrays;
  147.48 +
  147.49 +import static java.math.BigInteger.LONG_MASK;
  147.50 +import static java.math.BigDecimal.INFLATED;
  147.51 +
  147.52 +class MutableBigInteger {
  147.53 +    /**
  147.54 +     * Holds the magnitude of this MutableBigInteger in big endian order.
  147.55 +     * The magnitude may start at an offset into the value array, and it may
  147.56 +     * end before the length of the value array.
  147.57 +     */
  147.58 +    int[] value;
  147.59 +
  147.60 +    /**
  147.61 +     * The number of ints of the value array that are currently used
  147.62 +     * to hold the magnitude of this MutableBigInteger. The magnitude starts
  147.63 +     * at an offset and offset + intLen may be less than value.length.
  147.64 +     */
  147.65 +    int intLen;
  147.66 +
  147.67 +    /**
  147.68 +     * The offset into the value array where the magnitude of this
  147.69 +     * MutableBigInteger begins.
  147.70 +     */
  147.71 +    int offset = 0;
  147.72 +
  147.73 +    // Constants
  147.74 +    /**
  147.75 +     * MutableBigInteger with one element value array with the value 1. Used by
  147.76 +     * BigDecimal divideAndRound to increment the quotient. Use this constant
  147.77 +     * only when the method is not going to modify this object.
  147.78 +     */
  147.79 +    static final MutableBigInteger ONE = new MutableBigInteger(1);
  147.80 +
  147.81 +    // Constructors
  147.82 +
  147.83 +    /**
  147.84 +     * The default constructor. An empty MutableBigInteger is created with
  147.85 +     * a one word capacity.
  147.86 +     */
  147.87 +    MutableBigInteger() {
  147.88 +        value = new int[1];
  147.89 +        intLen = 0;
  147.90 +    }
  147.91 +
  147.92 +    /**
  147.93 +     * Construct a new MutableBigInteger with a magnitude specified by
  147.94 +     * the int val.
  147.95 +     */
  147.96 +    MutableBigInteger(int val) {
  147.97 +        value = new int[1];
  147.98 +        intLen = 1;
  147.99 +        value[0] = val;
 147.100 +    }
 147.101 +
 147.102 +    /**
 147.103 +     * Construct a new MutableBigInteger with the specified value array
 147.104 +     * up to the length of the array supplied.
 147.105 +     */
 147.106 +    MutableBigInteger(int[] val) {
 147.107 +        value = val;
 147.108 +        intLen = val.length;
 147.109 +    }
 147.110 +
 147.111 +    /**
 147.112 +     * Construct a new MutableBigInteger with a magnitude equal to the
 147.113 +     * specified BigInteger.
 147.114 +     */
 147.115 +    MutableBigInteger(BigInteger b) {
 147.116 +        intLen = b.mag.length;
 147.117 +        value = Arrays.copyOf(b.mag, intLen);
 147.118 +    }
 147.119 +
 147.120 +    /**
 147.121 +     * Construct a new MutableBigInteger with a magnitude equal to the
 147.122 +     * specified MutableBigInteger.
 147.123 +     */
 147.124 +    MutableBigInteger(MutableBigInteger val) {
 147.125 +        intLen = val.intLen;
 147.126 +        value = Arrays.copyOfRange(val.value, val.offset, val.offset + intLen);
 147.127 +    }
 147.128 +
 147.129 +    /**
 147.130 +     * Internal helper method to return the magnitude array. The caller is not
 147.131 +     * supposed to modify the returned array.
 147.132 +     */
 147.133 +    private int[] getMagnitudeArray() {
 147.134 +        if (offset > 0 || value.length != intLen)
 147.135 +            return Arrays.copyOfRange(value, offset, offset + intLen);
 147.136 +        return value;
 147.137 +    }
 147.138 +
 147.139 +    /**
 147.140 +     * Convert this MutableBigInteger to a long value. The caller has to make
 147.141 +     * sure this MutableBigInteger can be fit into long.
 147.142 +     */
 147.143 +    private long toLong() {
 147.144 +        assert (intLen <= 2) : "this MutableBigInteger exceeds the range of long";
 147.145 +        if (intLen == 0)
 147.146 +            return 0;
 147.147 +        long d = value[offset] & LONG_MASK;
 147.148 +        return (intLen == 2) ? d << 32 | (value[offset + 1] & LONG_MASK) : d;
 147.149 +    }
 147.150 +
 147.151 +    /**
 147.152 +     * Convert this MutableBigInteger to a BigInteger object.
 147.153 +     */
 147.154 +    BigInteger toBigInteger(int sign) {
 147.155 +        if (intLen == 0 || sign == 0)
 147.156 +            return BigInteger.ZERO;
 147.157 +        return new BigInteger(getMagnitudeArray(), sign);
 147.158 +    }
 147.159 +
 147.160 +    /**
 147.161 +     * Convert this MutableBigInteger to BigDecimal object with the specified sign
 147.162 +     * and scale.
 147.163 +     */
 147.164 +    BigDecimal toBigDecimal(int sign, int scale) {
 147.165 +        if (intLen == 0 || sign == 0)
 147.166 +            return BigDecimal.valueOf(0, scale);
 147.167 +        int[] mag = getMagnitudeArray();
 147.168 +        int len = mag.length;
 147.169 +        int d = mag[0];
 147.170 +        // If this MutableBigInteger can't be fit into long, we need to
 147.171 +        // make a BigInteger object for the resultant BigDecimal object.
 147.172 +        if (len > 2 || (d < 0 && len == 2))
 147.173 +            return new BigDecimal(new BigInteger(mag, sign), INFLATED, scale, 0);
 147.174 +        long v = (len == 2) ?
 147.175 +            ((mag[1] & LONG_MASK) | (d & LONG_MASK) << 32) :
 147.176 +            d & LONG_MASK;
 147.177 +        return new BigDecimal(null, sign == -1 ? -v : v, scale, 0);
 147.178 +    }
 147.179 +
 147.180 +    /**
 147.181 +     * Clear out a MutableBigInteger for reuse.
 147.182 +     */
 147.183 +    void clear() {
 147.184 +        offset = intLen = 0;
 147.185 +        for (int index=0, n=value.length; index < n; index++)
 147.186 +            value[index] = 0;
 147.187 +    }
 147.188 +
 147.189 +    /**
 147.190 +     * Set a MutableBigInteger to zero, removing its offset.
 147.191 +     */
 147.192 +    void reset() {
 147.193 +        offset = intLen = 0;
 147.194 +    }
 147.195 +
 147.196 +    /**
 147.197 +     * Compare the magnitude of two MutableBigIntegers. Returns -1, 0 or 1
 147.198 +     * as this MutableBigInteger is numerically less than, equal to, or
 147.199 +     * greater than <tt>b</tt>.
 147.200 +     */
 147.201 +    final int compare(MutableBigInteger b) {
 147.202 +        int blen = b.intLen;
 147.203 +        if (intLen < blen)
 147.204 +            return -1;
 147.205 +        if (intLen > blen)
 147.206 +           return 1;
 147.207 +
 147.208 +        // Add Integer.MIN_VALUE to make the comparison act as unsigned integer
 147.209 +        // comparison.
 147.210 +        int[] bval = b.value;
 147.211 +        for (int i = offset, j = b.offset; i < intLen + offset; i++, j++) {
 147.212 +            int b1 = value[i] + 0x80000000;
 147.213 +            int b2 = bval[j]  + 0x80000000;
 147.214 +            if (b1 < b2)
 147.215 +                return -1;
 147.216 +            if (b1 > b2)
 147.217 +                return 1;
 147.218 +        }
 147.219 +        return 0;
 147.220 +    }
 147.221 +
 147.222 +    /**
 147.223 +     * Compare this against half of a MutableBigInteger object (Needed for
 147.224 +     * remainder tests).
 147.225 +     * Assumes no leading unnecessary zeros, which holds for results
 147.226 +     * from divide().
 147.227 +     */
 147.228 +    final int compareHalf(MutableBigInteger b) {
 147.229 +        int blen = b.intLen;
 147.230 +        int len = intLen;
 147.231 +        if (len <= 0)
 147.232 +            return blen <=0 ? 0 : -1;
 147.233 +        if (len > blen)
 147.234 +            return 1;
 147.235 +        if (len < blen - 1)
 147.236 +            return -1;
 147.237 +        int[] bval = b.value;
 147.238 +        int bstart = 0;
 147.239 +        int carry = 0;
 147.240 +        // Only 2 cases left:len == blen or len == blen - 1
 147.241 +        if (len != blen) { // len == blen - 1
 147.242 +            if (bval[bstart] == 1) {
 147.243 +                ++bstart;
 147.244 +                carry = 0x80000000;
 147.245 +            } else
 147.246 +                return -1;
 147.247 +        }
 147.248 +        // compare values with right-shifted values of b,
 147.249 +        // carrying shifted-out bits across words
 147.250 +        int[] val = value;
 147.251 +        for (int i = offset, j = bstart; i < len + offset;) {
 147.252 +            int bv = bval[j++];
 147.253 +            long hb = ((bv >>> 1) + carry) & LONG_MASK;
 147.254 +            long v = val[i++] & LONG_MASK;
 147.255 +            if (v != hb)
 147.256 +                return v < hb ? -1 : 1;
 147.257 +            carry = (bv & 1) << 31; // carray will be either 0x80000000 or 0
 147.258 +        }
 147.259 +        return carry == 0? 0 : -1;
 147.260 +    }
 147.261 +
 147.262 +    /**
 147.263 +     * Return the index of the lowest set bit in this MutableBigInteger. If the
 147.264 +     * magnitude of this MutableBigInteger is zero, -1 is returned.
 147.265 +     */
 147.266 +    private final int getLowestSetBit() {
 147.267 +        if (intLen == 0)
 147.268 +            return -1;
 147.269 +        int j, b;
 147.270 +        for (j=intLen-1; (j>0) && (value[j+offset]==0); j--)
 147.271 +            ;
 147.272 +        b = value[j+offset];
 147.273 +        if (b==0)
 147.274 +            return -1;
 147.275 +        return ((intLen-1-j)<<5) + Integer.numberOfTrailingZeros(b);
 147.276 +    }
 147.277 +
 147.278 +    /**
 147.279 +     * Return the int in use in this MutableBigInteger at the specified
 147.280 +     * index. This method is not used because it is not inlined on all
 147.281 +     * platforms.
 147.282 +     */
 147.283 +    private final int getInt(int index) {
 147.284 +        return value[offset+index];
 147.285 +    }
 147.286 +
 147.287 +    /**
 147.288 +     * Return a long which is equal to the unsigned value of the int in
 147.289 +     * use in this MutableBigInteger at the specified index. This method is
 147.290 +     * not used because it is not inlined on all platforms.
 147.291 +     */
 147.292 +    private final long getLong(int index) {
 147.293 +        return value[offset+index] & LONG_MASK;
 147.294 +    }
 147.295 +
 147.296 +    /**
 147.297 +     * Ensure that the MutableBigInteger is in normal form, specifically
 147.298 +     * making sure that there are no leading zeros, and that if the
 147.299 +     * magnitude is zero, then intLen is zero.
 147.300 +     */
 147.301 +    final void normalize() {
 147.302 +        if (intLen == 0) {
 147.303 +            offset = 0;
 147.304 +            return;
 147.305 +        }
 147.306 +
 147.307 +        int index = offset;
 147.308 +        if (value[index] != 0)
 147.309 +            return;
 147.310 +
 147.311 +        int indexBound = index+intLen;
 147.312 +        do {
 147.313 +            index++;
 147.314 +        } while(index < indexBound && value[index]==0);
 147.315 +
 147.316 +        int numZeros = index - offset;
 147.317 +        intLen -= numZeros;
 147.318 +        offset = (intLen==0 ?  0 : offset+numZeros);
 147.319 +    }
 147.320 +
 147.321 +    /**
 147.322 +     * If this MutableBigInteger cannot hold len words, increase the size
 147.323 +     * of the value array to len words.
 147.324 +     */
 147.325 +    private final void ensureCapacity(int len) {
 147.326 +        if (value.length < len) {
 147.327 +            value = new int[len];
 147.328 +            offset = 0;
 147.329 +            intLen = len;
 147.330 +        }
 147.331 +    }
 147.332 +
 147.333 +    /**
 147.334 +     * Convert this MutableBigInteger into an int array with no leading
 147.335 +     * zeros, of a length that is equal to this MutableBigInteger's intLen.
 147.336 +     */
 147.337 +    int[] toIntArray() {
 147.338 +        int[] result = new int[intLen];
 147.339 +        for(int i=0; i<intLen; i++)
 147.340 +            result[i] = value[offset+i];
 147.341 +        return result;
 147.342 +    }
 147.343 +
 147.344 +    /**
 147.345 +     * Sets the int at index+offset in this MutableBigInteger to val.
 147.346 +     * This does not get inlined on all platforms so it is not used
 147.347 +     * as often as originally intended.
 147.348 +     */
 147.349 +    void setInt(int index, int val) {
 147.350 +        value[offset + index] = val;
 147.351 +    }
 147.352 +
 147.353 +    /**
 147.354 +     * Sets this MutableBigInteger's value array to the specified array.
 147.355 +     * The intLen is set to the specified length.
 147.356 +     */
 147.357 +    void setValue(int[] val, int length) {
 147.358 +        value = val;
 147.359 +        intLen = length;
 147.360 +        offset = 0;
 147.361 +    }
 147.362 +
 147.363 +    /**
 147.364 +     * Sets this MutableBigInteger's value array to a copy of the specified
 147.365 +     * array. The intLen is set to the length of the new array.
 147.366 +     */
 147.367 +    void copyValue(MutableBigInteger src) {
 147.368 +        int len = src.intLen;
 147.369 +        if (value.length < len)
 147.370 +            value = new int[len];
 147.371 +        System.arraycopy(src.value, src.offset, value, 0, len);
 147.372 +        intLen = len;
 147.373 +        offset = 0;
 147.374 +    }
 147.375 +
 147.376 +    /**
 147.377 +     * Sets this MutableBigInteger's value array to a copy of the specified
 147.378 +     * array. The intLen is set to the length of the specified array.
 147.379 +     */
 147.380 +    void copyValue(int[] val) {
 147.381 +        int len = val.length;
 147.382 +        if (value.length < len)
 147.383 +            value = new int[len];
 147.384 +        System.arraycopy(val, 0, value, 0, len);
 147.385 +        intLen = len;
 147.386 +        offset = 0;
 147.387 +    }
 147.388 +
 147.389 +    /**
 147.390 +     * Returns true iff this MutableBigInteger has a value of one.
 147.391 +     */
 147.392 +    boolean isOne() {
 147.393 +        return (intLen == 1) && (value[offset] == 1);
 147.394 +    }
 147.395 +
 147.396 +    /**
 147.397 +     * Returns true iff this MutableBigInteger has a value of zero.
 147.398 +     */
 147.399 +    boolean isZero() {
 147.400 +        return (intLen == 0);
 147.401 +    }
 147.402 +
 147.403 +    /**
 147.404 +     * Returns true iff this MutableBigInteger is even.
 147.405 +     */
 147.406 +    boolean isEven() {
 147.407 +        return (intLen == 0) || ((value[offset + intLen - 1] & 1) == 0);
 147.408 +    }
 147.409 +
 147.410 +    /**
 147.411 +     * Returns true iff this MutableBigInteger is odd.
 147.412 +     */
 147.413 +    boolean isOdd() {
 147.414 +        return isZero() ? false : ((value[offset + intLen - 1] & 1) == 1);
 147.415 +    }
 147.416 +
 147.417 +    /**
 147.418 +     * Returns true iff this MutableBigInteger is in normal form. A
 147.419 +     * MutableBigInteger is in normal form if it has no leading zeros
 147.420 +     * after the offset, and intLen + offset <= value.length.
 147.421 +     */
 147.422 +    boolean isNormal() {
 147.423 +        if (intLen + offset > value.length)
 147.424 +            return false;
 147.425 +        if (intLen ==0)
 147.426 +            return true;
 147.427 +        return (value[offset] != 0);
 147.428 +    }
 147.429 +
 147.430 +    /**
 147.431 +     * Returns a String representation of this MutableBigInteger in radix 10.
 147.432 +     */
 147.433 +    public String toString() {
 147.434 +        BigInteger b = toBigInteger(1);
 147.435 +        return b.toString();
 147.436 +    }
 147.437 +
 147.438 +    /**
 147.439 +     * Right shift this MutableBigInteger n bits. The MutableBigInteger is left
 147.440 +     * in normal form.
 147.441 +     */
 147.442 +    void rightShift(int n) {
 147.443 +        if (intLen == 0)
 147.444 +            return;
 147.445 +        int nInts = n >>> 5;
 147.446 +        int nBits = n & 0x1F;
 147.447 +        this.intLen -= nInts;
 147.448 +        if (nBits == 0)
 147.449 +            return;
 147.450 +        int bitsInHighWord = BigInteger.bitLengthForInt(value[offset]);
 147.451 +        if (nBits >= bitsInHighWord) {
 147.452 +            this.primitiveLeftShift(32 - nBits);
 147.453 +            this.intLen--;
 147.454 +        } else {
 147.455 +            primitiveRightShift(nBits);
 147.456 +        }
 147.457 +    }
 147.458 +
 147.459 +    /**
 147.460 +     * Left shift this MutableBigInteger n bits.
 147.461 +     */
 147.462 +    void leftShift(int n) {
 147.463 +        /*
 147.464 +         * If there is enough storage space in this MutableBigInteger already
 147.465 +         * the available space will be used. Space to the right of the used
 147.466 +         * ints in the value array is faster to utilize, so the extra space
 147.467 +         * will be taken from the right if possible.
 147.468 +         */
 147.469 +        if (intLen == 0)
 147.470 +           return;
 147.471 +        int nInts = n >>> 5;
 147.472 +        int nBits = n&0x1F;
 147.473 +        int bitsInHighWord = BigInteger.bitLengthForInt(value[offset]);
 147.474 +
 147.475 +        // If shift can be done without moving words, do so
 147.476 +        if (n <= (32-bitsInHighWord)) {
 147.477 +            primitiveLeftShift(nBits);
 147.478 +            return;
 147.479 +        }
 147.480 +
 147.481 +        int newLen = intLen + nInts +1;
 147.482 +        if (nBits <= (32-bitsInHighWord))
 147.483 +            newLen--;
 147.484 +        if (value.length < newLen) {
 147.485 +            // The array must grow
 147.486 +            int[] result = new int[newLen];
 147.487 +            for (int i=0; i<intLen; i++)
 147.488 +                result[i] = value[offset+i];
 147.489 +            setValue(result, newLen);
 147.490 +        } else if (value.length - offset >= newLen) {
 147.491 +            // Use space on right
 147.492 +            for(int i=0; i<newLen - intLen; i++)
 147.493 +                value[offset+intLen+i] = 0;
 147.494 +        } else {
 147.495 +            // Must use space on left
 147.496 +            for (int i=0; i<intLen; i++)
 147.497 +                value[i] = value[offset+i];
 147.498 +            for (int i=intLen; i<newLen; i++)
 147.499 +                value[i] = 0;
 147.500 +            offset = 0;
 147.501 +        }
 147.502 +        intLen = newLen;
 147.503 +        if (nBits == 0)
 147.504 +            return;
 147.505 +        if (nBits <= (32-bitsInHighWord))
 147.506 +            primitiveLeftShift(nBits);
 147.507 +        else
 147.508 +            primitiveRightShift(32 -nBits);
 147.509 +    }
 147.510 +
 147.511 +    /**
 147.512 +     * A primitive used for division. This method adds in one multiple of the
 147.513 +     * divisor a back to the dividend result at a specified offset. It is used
 147.514 +     * when qhat was estimated too large, and must be adjusted.
 147.515 +     */
 147.516 +    private int divadd(int[] a, int[] result, int offset) {
 147.517 +        long carry = 0;
 147.518 +
 147.519 +        for (int j=a.length-1; j >= 0; j--) {
 147.520 +            long sum = (a[j] & LONG_MASK) +
 147.521 +                       (result[j+offset] & LONG_MASK) + carry;
 147.522 +            result[j+offset] = (int)sum;
 147.523 +            carry = sum >>> 32;
 147.524 +        }
 147.525 +        return (int)carry;
 147.526 +    }
 147.527 +
 147.528 +    /**
 147.529 +     * This method is used for division. It multiplies an n word input a by one
 147.530 +     * word input x, and subtracts the n word product from q. This is needed
 147.531 +     * when subtracting qhat*divisor from dividend.
 147.532 +     */
 147.533 +    private int mulsub(int[] q, int[] a, int x, int len, int offset) {
 147.534 +        long xLong = x & LONG_MASK;
 147.535 +        long carry = 0;
 147.536 +        offset += len;
 147.537 +
 147.538 +        for (int j=len-1; j >= 0; j--) {
 147.539 +            long product = (a[j] & LONG_MASK) * xLong + carry;
 147.540 +            long difference = q[offset] - product;
 147.541 +            q[offset--] = (int)difference;
 147.542 +            carry = (product >>> 32)
 147.543 +                     + (((difference & LONG_MASK) >
 147.544 +                         (((~(int)product) & LONG_MASK))) ? 1:0);
 147.545 +        }
 147.546 +        return (int)carry;
 147.547 +    }
 147.548 +
 147.549 +    /**
 147.550 +     * Right shift this MutableBigInteger n bits, where n is
 147.551 +     * less than 32.
 147.552 +     * Assumes that intLen > 0, n > 0 for speed
 147.553 +     */
 147.554 +    private final void primitiveRightShift(int n) {
 147.555 +        int[] val = value;
 147.556 +        int n2 = 32 - n;
 147.557 +        for (int i=offset+intLen-1, c=val[i]; i>offset; i--) {
 147.558 +            int b = c;
 147.559 +            c = val[i-1];
 147.560 +            val[i] = (c << n2) | (b >>> n);
 147.561 +        }
 147.562 +        val[offset] >>>= n;
 147.563 +    }
 147.564 +
 147.565 +    /**
 147.566 +     * Left shift this MutableBigInteger n bits, where n is
 147.567 +     * less than 32.
 147.568 +     * Assumes that intLen > 0, n > 0 for speed
 147.569 +     */
 147.570 +    private final void primitiveLeftShift(int n) {
 147.571 +        int[] val = value;
 147.572 +        int n2 = 32 - n;
 147.573 +        for (int i=offset, c=val[i], m=i+intLen-1; i<m; i++) {
 147.574 +            int b = c;
 147.575 +            c = val[i+1];
 147.576 +            val[i] = (b << n) | (c >>> n2);
 147.577 +        }
 147.578 +        val[offset+intLen-1] <<= n;
 147.579 +    }
 147.580 +
 147.581 +    /**
 147.582 +     * Adds the contents of two MutableBigInteger objects.The result
 147.583 +     * is placed within this MutableBigInteger.
 147.584 +     * The contents of the addend are not changed.
 147.585 +     */
 147.586 +    void add(MutableBigInteger addend) {
 147.587 +        int x = intLen;
 147.588 +        int y = addend.intLen;
 147.589 +        int resultLen = (intLen > addend.intLen ? intLen : addend.intLen);
 147.590 +        int[] result = (value.length < resultLen ? new int[resultLen] : value);
 147.591 +
 147.592 +        int rstart = result.length-1;
 147.593 +        long sum;
 147.594 +        long carry = 0;
 147.595 +
 147.596 +        // Add common parts of both numbers
 147.597 +        while(x>0 && y>0) {
 147.598 +            x--; y--;
 147.599 +            sum = (value[x+offset] & LONG_MASK) +
 147.600 +                (addend.value[y+addend.offset] & LONG_MASK) + carry;
 147.601 +            result[rstart--] = (int)sum;
 147.602 +            carry = sum >>> 32;
 147.603 +        }
 147.604 +
 147.605 +        // Add remainder of the longer number
 147.606 +        while(x>0) {
 147.607 +            x--;
 147.608 +            if (carry == 0 && result == value && rstart == (x + offset))
 147.609 +                return;
 147.610 +            sum = (value[x+offset] & LONG_MASK) + carry;
 147.611 +            result[rstart--] = (int)sum;
 147.612 +            carry = sum >>> 32;
 147.613 +        }
 147.614 +        while(y>0) {
 147.615 +            y--;
 147.616 +            sum = (addend.value[y+addend.offset] & LONG_MASK) + carry;
 147.617 +            result[rstart--] = (int)sum;
 147.618 +            carry = sum >>> 32;
 147.619 +        }
 147.620 +
 147.621 +        if (carry > 0) { // Result must grow in length
 147.622 +            resultLen++;
 147.623 +            if (result.length < resultLen) {
 147.624 +                int temp[] = new int[resultLen];
 147.625 +                // Result one word longer from carry-out; copy low-order
 147.626 +                // bits into new result.
 147.627 +                System.arraycopy(result, 0, temp, 1, result.length);
 147.628 +                temp[0] = 1;
 147.629 +                result = temp;
 147.630 +            } else {
 147.631 +                result[rstart--] = 1;
 147.632 +            }
 147.633 +        }
 147.634 +
 147.635 +        value = result;
 147.636 +        intLen = resultLen;
 147.637 +        offset = result.length - resultLen;
 147.638 +    }
 147.639 +
 147.640 +
 147.641 +    /**
 147.642 +     * Subtracts the smaller of this and b from the larger and places the
 147.643 +     * result into this MutableBigInteger.
 147.644 +     */
 147.645 +    int subtract(MutableBigInteger b) {
 147.646 +        MutableBigInteger a = this;
 147.647 +
 147.648 +        int[] result = value;
 147.649 +        int sign = a.compare(b);
 147.650 +
 147.651 +        if (sign == 0) {
 147.652 +            reset();
 147.653 +            return 0;
 147.654 +        }
 147.655 +        if (sign < 0) {
 147.656 +            MutableBigInteger tmp = a;
 147.657 +            a = b;
 147.658 +            b = tmp;
 147.659 +        }
 147.660 +
 147.661 +        int resultLen = a.intLen;
 147.662 +        if (result.length < resultLen)
 147.663 +            result = new int[resultLen];
 147.664 +
 147.665 +        long diff = 0;
 147.666 +        int x = a.intLen;
 147.667 +        int y = b.intLen;
 147.668 +        int rstart = result.length - 1;
 147.669 +
 147.670 +        // Subtract common parts of both numbers
 147.671 +        while (y>0) {
 147.672 +            x--; y--;
 147.673 +
 147.674 +            diff = (a.value[x+a.offset] & LONG_MASK) -
 147.675 +                   (b.value[y+b.offset] & LONG_MASK) - ((int)-(diff>>32));
 147.676 +            result[rstart--] = (int)diff;
 147.677 +        }
 147.678 +        // Subtract remainder of longer number
 147.679 +        while (x>0) {
 147.680 +            x--;
 147.681 +            diff = (a.value[x+a.offset] & LONG_MASK) - ((int)-(diff>>32));
 147.682 +            result[rstart--] = (int)diff;
 147.683 +        }
 147.684 +
 147.685 +        value = result;
 147.686 +        intLen = resultLen;
 147.687 +        offset = value.length - resultLen;
 147.688 +        normalize();
 147.689 +        return sign;
 147.690 +    }
 147.691 +
 147.692 +    /**
 147.693 +     * Subtracts the smaller of a and b from the larger and places the result
 147.694 +     * into the larger. Returns 1 if the answer is in a, -1 if in b, 0 if no
 147.695 +     * operation was performed.
 147.696 +     */
 147.697 +    private int difference(MutableBigInteger b) {
 147.698 +        MutableBigInteger a = this;
 147.699 +        int sign = a.compare(b);
 147.700 +        if (sign ==0)
 147.701 +            return 0;
 147.702 +        if (sign < 0) {
 147.703 +            MutableBigInteger tmp = a;
 147.704 +            a = b;
 147.705 +            b = tmp;
 147.706 +        }
 147.707 +
 147.708 +        long diff = 0;
 147.709 +        int x = a.intLen;
 147.710 +        int y = b.intLen;
 147.711 +
 147.712 +        // Subtract common parts of both numbers
 147.713 +        while (y>0) {
 147.714 +            x--; y--;
 147.715 +            diff = (a.value[a.offset+ x] & LONG_MASK) -
 147.716 +                (b.value[b.offset+ y] & LONG_MASK) - ((int)-(diff>>32));
 147.717 +            a.value[a.offset+x] = (int)diff;
 147.718 +        }
 147.719 +        // Subtract remainder of longer number
 147.720 +        while (x>0) {
 147.721 +            x--;
 147.722 +            diff = (a.value[a.offset+ x] & LONG_MASK) - ((int)-(diff>>32));
 147.723 +            a.value[a.offset+x] = (int)diff;
 147.724 +        }
 147.725 +
 147.726 +        a.normalize();
 147.727 +        return sign;
 147.728 +    }
 147.729 +
 147.730 +    /**
 147.731 +     * Multiply the contents of two MutableBigInteger objects. The result is
 147.732 +     * placed into MutableBigInteger z. The contents of y are not changed.
 147.733 +     */
 147.734 +    void multiply(MutableBigInteger y, MutableBigInteger z) {
 147.735 +        int xLen = intLen;
 147.736 +        int yLen = y.intLen;
 147.737 +        int newLen = xLen + yLen;
 147.738 +
 147.739 +        // Put z into an appropriate state to receive product
 147.740 +        if (z.value.length < newLen)
 147.741 +            z.value = new int[newLen];
 147.742 +        z.offset = 0;
 147.743 +        z.intLen = newLen;
 147.744 +
 147.745 +        // The first iteration is hoisted out of the loop to avoid extra add
 147.746 +        long carry = 0;
 147.747 +        for (int j=yLen-1, k=yLen+xLen-1; j >= 0; j--, k--) {
 147.748 +                long product = (y.value[j+y.offset] & LONG_MASK) *
 147.749 +                               (value[xLen-1+offset] & LONG_MASK) + carry;
 147.750 +                z.value[k] = (int)product;
 147.751 +                carry = product >>> 32;
 147.752 +        }
 147.753 +        z.value[xLen-1] = (int)carry;
 147.754 +
 147.755 +        // Perform the multiplication word by word
 147.756 +        for (int i = xLen-2; i >= 0; i--) {
 147.757 +            carry = 0;
 147.758 +            for (int j=yLen-1, k=yLen+i; j >= 0; j--, k--) {
 147.759 +                long product = (y.value[j+y.offset] & LONG_MASK) *
 147.760 +                               (value[i+offset] & LONG_MASK) +
 147.761 +                               (z.value[k] & LONG_MASK) + carry;
 147.762 +                z.value[k] = (int)product;
 147.763 +                carry = product >>> 32;
 147.764 +            }
 147.765 +            z.value[i] = (int)carry;
 147.766 +        }
 147.767 +
 147.768 +        // Remove leading zeros from product
 147.769 +        z.normalize();
 147.770 +    }
 147.771 +
 147.772 +    /**
 147.773 +     * Multiply the contents of this MutableBigInteger by the word y. The
 147.774 +     * result is placed into z.
 147.775 +     */
 147.776 +    void mul(int y, MutableBigInteger z) {
 147.777 +        if (y == 1) {
 147.778 +            z.copyValue(this);
 147.779 +            return;
 147.780 +        }
 147.781 +
 147.782 +        if (y == 0) {
 147.783 +            z.clear();
 147.784 +            return;
 147.785 +        }
 147.786 +
 147.787 +        // Perform the multiplication word by word
 147.788 +        long ylong = y & LONG_MASK;
 147.789 +        int[] zval = (z.value.length<intLen+1 ? new int[intLen + 1]
 147.790 +                                              : z.value);
 147.791 +        long carry = 0;
 147.792 +        for (int i = intLen-1; i >= 0; i--) {
 147.793 +            long product = ylong * (value[i+offset] & LONG_MASK) + carry;
 147.794 +            zval[i+1] = (int)product;
 147.795 +            carry = product >>> 32;
 147.796 +        }
 147.797 +
 147.798 +        if (carry == 0) {
 147.799 +            z.offset = 1;
 147.800 +            z.intLen = intLen;
 147.801 +        } else {
 147.802 +            z.offset = 0;
 147.803 +            z.intLen = intLen + 1;
 147.804 +            zval[0] = (int)carry;
 147.805 +        }
 147.806 +        z.value = zval;
 147.807 +    }
 147.808 +
 147.809 +     /**
 147.810 +     * This method is used for division of an n word dividend by a one word
 147.811 +     * divisor. The quotient is placed into quotient. The one word divisor is
 147.812 +     * specified by divisor.
 147.813 +     *
 147.814 +     * @return the remainder of the division is returned.
 147.815 +     *
 147.816 +     */
 147.817 +    int divideOneWord(int divisor, MutableBigInteger quotient) {
 147.818 +        long divisorLong = divisor & LONG_MASK;
 147.819 +
 147.820 +        // Special case of one word dividend
 147.821 +        if (intLen == 1) {
 147.822 +            long dividendValue = value[offset] & LONG_MASK;
 147.823 +            int q = (int) (dividendValue / divisorLong);
 147.824 +            int r = (int) (dividendValue - q * divisorLong);
 147.825 +            quotient.value[0] = q;
 147.826 +            quotient.intLen = (q == 0) ? 0 : 1;
 147.827 +            quotient.offset = 0;
 147.828 +            return r;
 147.829 +        }
 147.830 +
 147.831 +        if (quotient.value.length < intLen)
 147.832 +            quotient.value = new int[intLen];
 147.833 +        quotient.offset = 0;
 147.834 +        quotient.intLen = intLen;
 147.835 +
 147.836 +        // Normalize the divisor
 147.837 +        int shift = Integer.numberOfLeadingZeros(divisor);
 147.838 +
 147.839 +        int rem = value[offset];
 147.840 +        long remLong = rem & LONG_MASK;
 147.841 +        if (remLong < divisorLong) {
 147.842 +            quotient.value[0] = 0;
 147.843 +        } else {
 147.844 +            quotient.value[0] = (int)(remLong / divisorLong);
 147.845 +            rem = (int) (remLong - (quotient.value[0] * divisorLong));
 147.846 +            remLong = rem & LONG_MASK;
 147.847 +        }
 147.848 +
 147.849 +        int xlen = intLen;
 147.850 +        int[] qWord = new int[2];
 147.851 +        while (--xlen > 0) {
 147.852 +            long dividendEstimate = (remLong<<32) |
 147.853 +                (value[offset + intLen - xlen] & LONG_MASK);
 147.854 +            if (dividendEstimate >= 0) {
 147.855 +                qWord[0] = (int) (dividendEstimate / divisorLong);
 147.856 +                qWord[1] = (int) (dividendEstimate - qWord[0] * divisorLong);
 147.857 +            } else {
 147.858 +                divWord(qWord, dividendEstimate, divisor);
 147.859 +            }
 147.860 +            quotient.value[intLen - xlen] = qWord[0];
 147.861 +            rem = qWord[1];
 147.862 +            remLong = rem & LONG_MASK;
 147.863 +        }
 147.864 +
 147.865 +        quotient.normalize();
 147.866 +        // Unnormalize
 147.867 +        if (shift > 0)
 147.868 +            return rem % divisor;
 147.869 +        else
 147.870 +            return rem;
 147.871 +    }
 147.872 +
 147.873 +    /**
 147.874 +     * Calculates the quotient of this div b and places the quotient in the
 147.875 +     * provided MutableBigInteger objects and the remainder object is returned.
 147.876 +     *
 147.877 +     * Uses Algorithm D in Knuth section 4.3.1.
 147.878 +     * Many optimizations to that algorithm have been adapted from the Colin
 147.879 +     * Plumb C library.
 147.880 +     * It special cases one word divisors for speed. The content of b is not
 147.881 +     * changed.
 147.882 +     *
 147.883 +     */
 147.884 +    MutableBigInteger divide(MutableBigInteger b, MutableBigInteger quotient) {
 147.885 +        if (b.intLen == 0)
 147.886 +            throw new ArithmeticException("BigInteger divide by zero");
 147.887 +
 147.888 +        // Dividend is zero
 147.889 +        if (intLen == 0) {
 147.890 +            quotient.intLen = quotient.offset;
 147.891 +            return new MutableBigInteger();
 147.892 +        }
 147.893 +
 147.894 +        int cmp = compare(b);
 147.895 +        // Dividend less than divisor
 147.896 +        if (cmp < 0) {
 147.897 +            quotient.intLen = quotient.offset = 0;
 147.898 +            return new MutableBigInteger(this);
 147.899 +        }
 147.900 +        // Dividend equal to divisor
 147.901 +        if (cmp == 0) {
 147.902 +            quotient.value[0] = quotient.intLen = 1;
 147.903 +            quotient.offset = 0;
 147.904 +            return new MutableBigInteger();
 147.905 +        }
 147.906 +
 147.907 +        quotient.clear();
 147.908 +        // Special case one word divisor
 147.909 +        if (b.intLen == 1) {
 147.910 +            int r = divideOneWord(b.value[b.offset], quotient);
 147.911 +            if (r == 0)
 147.912 +                return new MutableBigInteger();
 147.913 +            return new MutableBigInteger(r);
 147.914 +        }
 147.915 +
 147.916 +        // Copy divisor value to protect divisor
 147.917 +        int[] div = Arrays.copyOfRange(b.value, b.offset, b.offset + b.intLen);
 147.918 +        return divideMagnitude(div, quotient);
 147.919 +    }
 147.920 +
 147.921 +    /**
 147.922 +     * Internally used  to calculate the quotient of this div v and places the
 147.923 +     * quotient in the provided MutableBigInteger object and the remainder is
 147.924 +     * returned.
 147.925 +     *
 147.926 +     * @return the remainder of the division will be returned.
 147.927 +     */
 147.928 +    long divide(long v, MutableBigInteger quotient) {
 147.929 +        if (v == 0)
 147.930 +            throw new ArithmeticException("BigInteger divide by zero");
 147.931 +
 147.932 +        // Dividend is zero
 147.933 +        if (intLen == 0) {
 147.934 +            quotient.intLen = quotient.offset = 0;
 147.935 +            return 0;
 147.936 +        }
 147.937 +        if (v < 0)
 147.938 +            v = -v;
 147.939 +
 147.940 +        int d = (int)(v >>> 32);
 147.941 +        quotient.clear();
 147.942 +        // Special case on word divisor
 147.943 +        if (d == 0)
 147.944 +            return divideOneWord((int)v, quotient) & LONG_MASK;
 147.945 +        else {
 147.946 +            int[] div = new int[]{ d, (int)(v & LONG_MASK) };
 147.947 +            return divideMagnitude(div, quotient).toLong();
 147.948 +        }
 147.949 +    }
 147.950 +
 147.951 +    /**
 147.952 +     * Divide this MutableBigInteger by the divisor represented by its magnitude
 147.953 +     * array. The quotient will be placed into the provided quotient object &
 147.954 +     * the remainder object is returned.
 147.955 +     */
 147.956 +    private MutableBigInteger divideMagnitude(int[] divisor,
 147.957 +                                              MutableBigInteger quotient) {
 147.958 +
 147.959 +        // Remainder starts as dividend with space for a leading zero
 147.960 +        MutableBigInteger rem = new MutableBigInteger(new int[intLen + 1]);
 147.961 +        System.arraycopy(value, offset, rem.value, 1, intLen);
 147.962 +        rem.intLen = intLen;
 147.963 +        rem.offset = 1;
 147.964 +
 147.965 +        int nlen = rem.intLen;
 147.966 +
 147.967 +        // Set the quotient size
 147.968 +        int dlen = divisor.length;
 147.969 +        int limit = nlen - dlen + 1;
 147.970 +        if (quotient.value.length < limit) {
 147.971 +            quotient.value = new int[limit];
 147.972 +            quotient.offset = 0;
 147.973 +        }
 147.974 +        quotient.intLen = limit;
 147.975 +        int[] q = quotient.value;
 147.976 +
 147.977 +        // D1 normalize the divisor
 147.978 +        int shift = Integer.numberOfLeadingZeros(divisor[0]);
 147.979 +        if (shift > 0) {
 147.980 +            // First shift will not grow array
 147.981 +            BigInteger.primitiveLeftShift(divisor, dlen, shift);
 147.982 +            // But this one might
 147.983 +            rem.leftShift(shift);
 147.984 +        }
 147.985 +
 147.986 +        // Must insert leading 0 in rem if its length did not change
 147.987 +        if (rem.intLen == nlen) {
 147.988 +            rem.offset = 0;
 147.989 +            rem.value[0] = 0;
 147.990 +            rem.intLen++;
 147.991 +        }
 147.992 +
 147.993 +        int dh = divisor[0];
 147.994 +        long dhLong = dh & LONG_MASK;
 147.995 +        int dl = divisor[1];
 147.996 +        int[] qWord = new int[2];
 147.997 +
 147.998 +        // D2 Initialize j
 147.999 +        for(int j=0; j<limit; j++) {
147.1000 +            // D3 Calculate qhat
147.1001 +            // estimate qhat
147.1002 +            int qhat = 0;
147.1003 +            int qrem = 0;
147.1004 +            boolean skipCorrection = false;
147.1005 +            int nh = rem.value[j+rem.offset];
147.1006 +            int nh2 = nh + 0x80000000;
147.1007 +            int nm = rem.value[j+1+rem.offset];
147.1008 +
147.1009 +            if (nh == dh) {
147.1010 +                qhat = ~0;
147.1011 +                qrem = nh + nm;
147.1012 +                skipCorrection = qrem + 0x80000000 < nh2;
147.1013 +            } else {
147.1014 +                long nChunk = (((long)nh) << 32) | (nm & LONG_MASK);
147.1015 +                if (nChunk >= 0) {
147.1016 +                    qhat = (int) (nChunk / dhLong);
147.1017 +                    qrem = (int) (nChunk - (qhat * dhLong));
147.1018 +                } else {
147.1019 +                    divWord(qWord, nChunk, dh);
147.1020 +                    qhat = qWord[0];
147.1021 +                    qrem = qWord[1];
147.1022 +                }
147.1023 +            }
147.1024 +
147.1025 +            if (qhat == 0)
147.1026 +                continue;
147.1027 +
147.1028 +            if (!skipCorrection) { // Correct qhat
147.1029 +                long nl = rem.value[j+2+rem.offset] & LONG_MASK;
147.1030 +                long rs = ((qrem & LONG_MASK) << 32) | nl;
147.1031 +                long estProduct = (dl & LONG_MASK) * (qhat & LONG_MASK);
147.1032 +
147.1033 +                if (unsignedLongCompare(estProduct, rs)) {
147.1034 +                    qhat--;
147.1035 +                    qrem = (int)((qrem & LONG_MASK) + dhLong);
147.1036 +                    if ((qrem & LONG_MASK) >=  dhLong) {
147.1037 +                        estProduct -= (dl & LONG_MASK);
147.1038 +                        rs = ((qrem & LONG_MASK) << 32) | nl;
147.1039 +                        if (unsignedLongCompare(estProduct, rs))
147.1040 +                            qhat--;
147.1041 +                    }
147.1042 +                }
147.1043 +            }
147.1044 +
147.1045 +            // D4 Multiply and subtract
147.1046 +            rem.value[j+rem.offset] = 0;
147.1047 +            int borrow = mulsub(rem.value, divisor, qhat, dlen, j+rem.offset);
147.1048 +
147.1049 +            // D5 Test remainder
147.1050 +            if (borrow + 0x80000000 > nh2) {
147.1051 +                // D6 Add back
147.1052 +                divadd(divisor, rem.value, j+1+rem.offset);
147.1053 +                qhat--;
147.1054 +            }
147.1055 +
147.1056 +            // Store the quotient digit
147.1057 +            q[j] = qhat;
147.1058 +        } // D7 loop on j
147.1059 +
147.1060 +        // D8 Unnormalize
147.1061 +        if (shift > 0)
147.1062 +            rem.rightShift(shift);
147.1063 +
147.1064 +        quotient.normalize();
147.1065 +        rem.normalize();
147.1066 +        return rem;
147.1067 +    }
147.1068 +
147.1069 +    /**
147.1070 +     * Compare two longs as if they were unsigned.
147.1071 +     * Returns true iff one is bigger than two.
147.1072 +     */
147.1073 +    private boolean unsignedLongCompare(long one, long two) {
147.1074 +        return (one+Long.MIN_VALUE) > (two+Long.MIN_VALUE);
147.1075 +    }
147.1076 +
147.1077 +    /**
147.1078 +     * This method divides a long quantity by an int to estimate
147.1079 +     * qhat for two multi precision numbers. It is used when
147.1080 +     * the signed value of n is less than zero.
147.1081 +     */
147.1082 +    private void divWord(int[] result, long n, int d) {
147.1083 +        long dLong = d & LONG_MASK;
147.1084 +
147.1085 +        if (dLong == 1) {
147.1086 +            result[0] = (int)n;
147.1087 +            result[1] = 0;
147.1088 +            return;
147.1089 +        }
147.1090 +
147.1091 +        // Approximate the quotient and remainder
147.1092 +        long q = (n >>> 1) / (dLong >>> 1);
147.1093 +        long r = n - q*dLong;
147.1094 +
147.1095 +        // Correct the approximation
147.1096 +        while (r < 0) {
147.1097 +            r += dLong;
147.1098 +            q--;
147.1099 +        }
147.1100 +        while (r >= dLong) {
147.1101 +            r -= dLong;
147.1102 +            q++;
147.1103 +        }
147.1104 +
147.1105 +        // n - q*dlong == r && 0 <= r <dLong, hence we're done.
147.1106 +        result[0] = (int)q;
147.1107 +        result[1] = (int)r;
147.1108 +    }
147.1109 +
147.1110 +    /**
147.1111 +     * Calculate GCD of this and b. This and b are changed by the computation.
147.1112 +     */
147.1113 +    MutableBigInteger hybridGCD(MutableBigInteger b) {
147.1114 +        // Use Euclid's algorithm until the numbers are approximately the
147.1115 +        // same length, then use the binary GCD algorithm to find the GCD.
147.1116 +        MutableBigInteger a = this;
147.1117 +        MutableBigInteger q = new MutableBigInteger();
147.1118 +
147.1119 +        while (b.intLen != 0) {
147.1120 +            if (Math.abs(a.intLen - b.intLen) < 2)
147.1121 +                return a.binaryGCD(b);
147.1122 +
147.1123 +            MutableBigInteger r = a.divide(b, q);
147.1124 +            a = b;
147.1125 +            b = r;
147.1126 +        }
147.1127 +        return a;
147.1128 +    }
147.1129 +
147.1130 +    /**
147.1131 +     * Calculate GCD of this and v.
147.1132 +     * Assumes that this and v are not zero.
147.1133 +     */
147.1134 +    private MutableBigInteger binaryGCD(MutableBigInteger v) {
147.1135 +        // Algorithm B from Knuth section 4.5.2
147.1136 +        MutableBigInteger u = this;
147.1137 +        MutableBigInteger r = new MutableBigInteger();
147.1138 +
147.1139 +        // step B1
147.1140 +        int s1 = u.getLowestSetBit();
147.1141 +        int s2 = v.getLowestSetBit();
147.1142 +        int k = (s1 < s2) ? s1 : s2;
147.1143 +        if (k != 0) {
147.1144 +            u.rightShift(k);
147.1145 +            v.rightShift(k);
147.1146 +        }
147.1147 +
147.1148 +        // step B2
147.1149 +        boolean uOdd = (k==s1);
147.1150 +        MutableBigInteger t = uOdd ? v: u;
147.1151 +        int tsign = uOdd ? -1 : 1;
147.1152 +
147.1153 +        int lb;
147.1154 +        while ((lb = t.getLowestSetBit()) >= 0) {
147.1155 +            // steps B3 and B4
147.1156 +            t.rightShift(lb);
147.1157 +            // step B5
147.1158 +            if (tsign > 0)
147.1159 +                u = t;
147.1160 +            else
147.1161 +                v = t;
147.1162 +
147.1163 +            // Special case one word numbers
147.1164 +            if (u.intLen < 2 && v.intLen < 2) {
147.1165 +                int x = u.value[u.offset];
147.1166 +                int y = v.value[v.offset];
147.1167 +                x  = binaryGcd(x, y);
147.1168 +                r.value[0] = x;
147.1169 +                r.intLen = 1;
147.1170 +                r.offset = 0;
147.1171 +                if (k > 0)
147.1172 +                    r.leftShift(k);
147.1173 +                return r;
147.1174 +            }
147.1175 +
147.1176 +            // step B6
147.1177 +            if ((tsign = u.difference(v)) == 0)
147.1178 +                break;
147.1179 +            t = (tsign >= 0) ? u : v;
147.1180 +        }
147.1181 +
147.1182 +        if (k > 0)
147.1183 +            u.leftShift(k);
147.1184 +        return u;
147.1185 +    }
147.1186 +
147.1187 +    /**
147.1188 +     * Calculate GCD of a and b interpreted as unsigned integers.
147.1189 +     */
147.1190 +    static int binaryGcd(int a, int b) {
147.1191 +        if (b==0)
147.1192 +            return a;
147.1193 +        if (a==0)
147.1194 +            return b;
147.1195 +
147.1196 +        // Right shift a & b till their last bits equal to 1.
147.1197 +        int aZeros = Integer.numberOfTrailingZeros(a);
147.1198 +        int bZeros = Integer.numberOfTrailingZeros(b);
147.1199 +        a >>>= aZeros;
147.1200 +        b >>>= bZeros;
147.1201 +
147.1202 +        int t = (aZeros < bZeros ? aZeros : bZeros);
147.1203 +
147.1204 +        while (a != b) {
147.1205 +            if ((a+0x80000000) > (b+0x80000000)) {  // a > b as unsigned
147.1206 +                a -= b;
147.1207 +                a >>>= Integer.numberOfTrailingZeros(a);
147.1208 +            } else {
147.1209 +                b -= a;
147.1210 +                b >>>= Integer.numberOfTrailingZeros(b);
147.1211 +            }
147.1212 +        }
147.1213 +        return a<<t;
147.1214 +    }
147.1215 +
147.1216 +    /**
147.1217 +     * Returns the modInverse of this mod p. This and p are not affected by
147.1218 +     * the operation.
147.1219 +     */
147.1220 +    MutableBigInteger mutableModInverse(MutableBigInteger p) {
147.1221 +        // Modulus is odd, use Schroeppel's algorithm
147.1222 +        if (p.isOdd())
147.1223 +            return modInverse(p);
147.1224 +
147.1225 +        // Base and modulus are even, throw exception
147.1226 +        if (isEven())
147.1227 +            throw new ArithmeticException("BigInteger not invertible.");
147.1228 +
147.1229 +        // Get even part of modulus expressed as a power of 2
147.1230 +        int powersOf2 = p.getLowestSetBit();
147.1231 +
147.1232 +        // Construct odd part of modulus
147.1233 +        MutableBigInteger oddMod = new MutableBigInteger(p);
147.1234 +        oddMod.rightShift(powersOf2);
147.1235 +
147.1236 +        if (oddMod.isOne())
147.1237 +            return modInverseMP2(powersOf2);
147.1238 +
147.1239 +        // Calculate 1/a mod oddMod
147.1240 +        MutableBigInteger oddPart = modInverse(oddMod);
147.1241 +
147.1242 +        // Calculate 1/a mod evenMod
147.1243 +        MutableBigInteger evenPart = modInverseMP2(powersOf2);
147.1244 +
147.1245 +        // Combine the results using Chinese Remainder Theorem
147.1246 +        MutableBigInteger y1 = modInverseBP2(oddMod, powersOf2);
147.1247 +        MutableBigInteger y2 = oddMod.modInverseMP2(powersOf2);
147.1248 +
147.1249 +        MutableBigInteger temp1 = new MutableBigInteger();
147.1250 +        MutableBigInteger temp2 = new MutableBigInteger();
147.1251 +        MutableBigInteger result = new MutableBigInteger();
147.1252 +
147.1253 +        oddPart.leftShift(powersOf2);
147.1254 +        oddPart.multiply(y1, result);
147.1255 +
147.1256 +        evenPart.multiply(oddMod, temp1);
147.1257 +        temp1.multiply(y2, temp2);
147.1258 +
147.1259 +        result.add(temp2);
147.1260 +        return result.divide(p, temp1);
147.1261 +    }
147.1262 +
147.1263 +    /*
147.1264 +     * Calculate the multiplicative inverse of this mod 2^k.
147.1265 +     */
147.1266 +    MutableBigInteger modInverseMP2(int k) {
147.1267 +        if (isEven())
147.1268 +            throw new ArithmeticException("Non-invertible. (GCD != 1)");
147.1269 +
147.1270 +        if (k > 64)
147.1271 +            return euclidModInverse(k);
147.1272 +
147.1273 +        int t = inverseMod32(value[offset+intLen-1]);
147.1274 +
147.1275 +        if (k < 33) {
147.1276 +            t = (k == 32 ? t : t & ((1 << k) - 1));
147.1277 +            return new MutableBigInteger(t);
147.1278 +        }
147.1279 +
147.1280 +        long pLong = (value[offset+intLen-1] & LONG_MASK);
147.1281 +        if (intLen > 1)
147.1282 +            pLong |=  ((long)value[offset+intLen-2] << 32);
147.1283 +        long tLong = t & LONG_MASK;
147.1284 +        tLong = tLong * (2 - pLong * tLong);  // 1 more Newton iter step
147.1285 +        tLong = (k == 64 ? tLong : tLong & ((1L << k) - 1));
147.1286 +
147.1287 +        MutableBigInteger result = new MutableBigInteger(new int[2]);
147.1288 +        result.value[0] = (int)(tLong >>> 32);
147.1289 +        result.value[1] = (int)tLong;
147.1290 +        result.intLen = 2;
147.1291 +        result.normalize();
147.1292 +        return result;
147.1293 +    }
147.1294 +
147.1295 +    /*
147.1296 +     * Returns the multiplicative inverse of val mod 2^32.  Assumes val is odd.
147.1297 +     */
147.1298 +    static int inverseMod32(int val) {
147.1299 +        // Newton's iteration!
147.1300 +        int t = val;
147.1301 +        t *= 2 - val*t;
147.1302 +        t *= 2 - val*t;
147.1303 +        t *= 2 - val*t;
147.1304 +        t *= 2 - val*t;
147.1305 +        return t;
147.1306 +    }
147.1307 +
147.1308 +    /*
147.1309 +     * Calculate the multiplicative inverse of 2^k mod mod, where mod is odd.
147.1310 +     */
147.1311 +    static MutableBigInteger modInverseBP2(MutableBigInteger mod, int k) {
147.1312 +        // Copy the mod to protect original
147.1313 +        return fixup(new MutableBigInteger(1), new MutableBigInteger(mod), k);
147.1314 +    }
147.1315 +
147.1316 +    /**
147.1317 +     * Calculate the multiplicative inverse of this mod mod, where mod is odd.
147.1318 +     * This and mod are not changed by the calculation.
147.1319 +     *
147.1320 +     * This method implements an algorithm due to Richard Schroeppel, that uses
147.1321 +     * the same intermediate representation as Montgomery Reduction
147.1322 +     * ("Montgomery Form").  The algorithm is described in an unpublished
147.1323 +     * manuscript entitled "Fast Modular Reciprocals."
147.1324 +     */
147.1325 +    private MutableBigInteger modInverse(MutableBigInteger mod) {
147.1326 +        MutableBigInteger p = new MutableBigInteger(mod);
147.1327 +        MutableBigInteger f = new MutableBigInteger(this);
147.1328 +        MutableBigInteger g = new MutableBigInteger(p);
147.1329 +        SignedMutableBigInteger c = new SignedMutableBigInteger(1);
147.1330 +        SignedMutableBigInteger d = new SignedMutableBigInteger();
147.1331 +        MutableBigInteger temp = null;
147.1332 +        SignedMutableBigInteger sTemp = null;
147.1333 +
147.1334 +        int k = 0;
147.1335 +        // Right shift f k times until odd, left shift d k times
147.1336 +        if (f.isEven()) {
147.1337 +            int trailingZeros = f.getLowestSetBit();
147.1338 +            f.rightShift(trailingZeros);
147.1339 +            d.leftShift(trailingZeros);
147.1340 +            k = trailingZeros;
147.1341 +        }
147.1342 +
147.1343 +        // The Almost Inverse Algorithm
147.1344 +        while(!f.isOne()) {
147.1345 +            // If gcd(f, g) != 1, number is not invertible modulo mod
147.1346 +            if (f.isZero())
147.1347 +                throw new ArithmeticException("BigInteger not invertible.");
147.1348 +
147.1349 +            // If f < g exchange f, g and c, d
147.1350 +            if (f.compare(g) < 0) {
147.1351 +                temp = f; f = g; g = temp;
147.1352 +                sTemp = d; d = c; c = sTemp;
147.1353 +            }
147.1354 +
147.1355 +            // If f == g (mod 4)
147.1356 +            if (((f.value[f.offset + f.intLen - 1] ^
147.1357 +                 g.value[g.offset + g.intLen - 1]) & 3) == 0) {
147.1358 +                f.subtract(g);
147.1359 +                c.signedSubtract(d);
147.1360 +            } else { // If f != g (mod 4)
147.1361 +                f.add(g);
147.1362 +                c.signedAdd(d);
147.1363 +            }
147.1364 +
147.1365 +            // Right shift f k times until odd, left shift d k times
147.1366 +            int trailingZeros = f.getLowestSetBit();
147.1367 +            f.rightShift(trailingZeros);
147.1368 +            d.leftShift(trailingZeros);
147.1369 +            k += trailingZeros;
147.1370 +        }
147.1371 +
147.1372 +        while (c.sign < 0)
147.1373 +           c.signedAdd(p);
147.1374 +
147.1375 +        return fixup(c, p, k);
147.1376 +    }
147.1377 +
147.1378 +    /*
147.1379 +     * The Fixup Algorithm
147.1380 +     * Calculates X such that X = C * 2^(-k) (mod P)
147.1381 +     * Assumes C<P and P is odd.
147.1382 +     */
147.1383 +    static MutableBigInteger fixup(MutableBigInteger c, MutableBigInteger p,
147.1384 +                                                                      int k) {
147.1385 +        MutableBigInteger temp = new MutableBigInteger();
147.1386 +        // Set r to the multiplicative inverse of p mod 2^32
147.1387 +        int r = -inverseMod32(p.value[p.offset+p.intLen-1]);
147.1388 +
147.1389 +        for(int i=0, numWords = k >> 5; i<numWords; i++) {
147.1390 +            // V = R * c (mod 2^j)
147.1391 +            int  v = r * c.value[c.offset + c.intLen-1];
147.1392 +            // c = c + (v * p)
147.1393 +            p.mul(v, temp);
147.1394 +            c.add(temp);
147.1395 +            // c = c / 2^j
147.1396 +            c.intLen--;
147.1397 +        }
147.1398 +        int numBits = k & 0x1f;
147.1399 +        if (numBits != 0) {
147.1400 +            // V = R * c (mod 2^j)
147.1401 +            int v = r * c.value[c.offset + c.intLen-1];
147.1402 +            v &= ((1<<numBits) - 1);
147.1403 +            // c = c + (v * p)
147.1404 +            p.mul(v, temp);
147.1405 +            c.add(temp);
147.1406 +            // c = c / 2^j
147.1407 +            c.rightShift(numBits);
147.1408 +        }
147.1409 +
147.1410 +        // In theory, c may be greater than p at this point (Very rare!)
147.1411 +        while (c.compare(p) >= 0)
147.1412 +            c.subtract(p);
147.1413 +
147.1414 +        return c;
147.1415 +    }
147.1416 +
147.1417 +    /**
147.1418 +     * Uses the extended Euclidean algorithm to compute the modInverse of base
147.1419 +     * mod a modulus that is a power of 2. The modulus is 2^k.
147.1420 +     */
147.1421 +    MutableBigInteger euclidModInverse(int k) {
147.1422 +        MutableBigInteger b = new MutableBigInteger(1);
147.1423 +        b.leftShift(k);
147.1424 +        MutableBigInteger mod = new MutableBigInteger(b);
147.1425 +
147.1426 +        MutableBigInteger a = new MutableBigInteger(this);
147.1427 +        MutableBigInteger q = new MutableBigInteger();
147.1428 +        MutableBigInteger r = b.divide(a, q);
147.1429 +
147.1430 +        MutableBigInteger swapper = b;
147.1431 +        // swap b & r
147.1432 +        b = r;
147.1433 +        r = swapper;
147.1434 +
147.1435 +        MutableBigInteger t1 = new MutableBigInteger(q);
147.1436 +        MutableBigInteger t0 = new MutableBigInteger(1);
147.1437 +        MutableBigInteger temp = new MutableBigInteger();
147.1438 +
147.1439 +        while (!b.isOne()) {
147.1440 +            r = a.divide(b, q);
147.1441 +
147.1442 +            if (r.intLen == 0)
147.1443 +                throw new ArithmeticException("BigInteger not invertible.");
147.1444 +
147.1445 +            swapper = r;
147.1446 +            a = swapper;
147.1447 +
147.1448 +            if (q.intLen == 1)
147.1449 +                t1.mul(q.value[q.offset], temp);
147.1450 +            else
147.1451 +                q.multiply(t1, temp);
147.1452 +            swapper = q;
147.1453 +            q = temp;
147.1454 +            temp = swapper;
147.1455 +            t0.add(q);
147.1456 +
147.1457 +            if (a.isOne())
147.1458 +                return t0;
147.1459 +
147.1460 +            r = b.divide(a, q);
147.1461 +
147.1462 +            if (r.intLen == 0)
147.1463 +                throw new ArithmeticException("BigInteger not invertible.");
147.1464 +
147.1465 +            swapper = b;
147.1466 +            b =  r;
147.1467 +
147.1468 +            if (q.intLen == 1)
147.1469 +                t0.mul(q.value[q.offset], temp);
147.1470 +            else
147.1471 +                q.multiply(t0, temp);
147.1472 +            swapper = q; q = temp; temp = swapper;
147.1473 +
147.1474 +            t1.add(q);
147.1475 +        }
147.1476 +        mod.subtract(t1);
147.1477 +        return mod;
147.1478 +    }
147.1479 +
147.1480 +}
   148.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   148.2 +++ b/rt/emul/compact/src/main/java/java/math/RoundingMode.java	Mon Oct 07 14:20:58 2013 +0200
   148.3 @@ -0,0 +1,349 @@
   148.4 +/*
   148.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   148.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   148.7 + *
   148.8 + * This code is free software; you can redistribute it and/or modify it
   148.9 + * under the terms of the GNU General Public License version 2 only, as
  148.10 + * published by the Free Software Foundation.  Oracle designates this
  148.11 + * particular file as subject to the "Classpath" exception as provided
  148.12 + * by Oracle in the LICENSE file that accompanied this code.
  148.13 + *
  148.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  148.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  148.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  148.17 + * version 2 for more details (a copy is included in the LICENSE file that
  148.18 + * accompanied this code).
  148.19 + *
  148.20 + * You should have received a copy of the GNU General Public License version
  148.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  148.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  148.23 + *
  148.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  148.25 + * or visit www.oracle.com if you need additional information or have any
  148.26 + * questions.
  148.27 + */
  148.28 +
  148.29 +/*
  148.30 + * Portions Copyright IBM Corporation, 2001. All Rights Reserved.
  148.31 + */
  148.32 +package java.math;
  148.33 +
  148.34 +/**
  148.35 + * Specifies a <i>rounding behavior</i> for numerical operations
  148.36 + * capable of discarding precision. Each rounding mode indicates how
  148.37 + * the least significant returned digit of a rounded result is to be
  148.38 + * calculated.  If fewer digits are returned than the digits needed to
  148.39 + * represent the exact numerical result, the discarded digits will be
  148.40 + * referred to as the <i>discarded fraction</i> regardless the digits'
  148.41 + * contribution to the value of the number.  In other words,
  148.42 + * considered as a numerical value, the discarded fraction could have
  148.43 + * an absolute value greater than one.
  148.44 + *
  148.45 + * <p>Each rounding mode description includes a table listing how
  148.46 + * different two-digit decimal values would round to a one digit
  148.47 + * decimal value under the rounding mode in question.  The result
  148.48 + * column in the tables could be gotten by creating a
  148.49 + * {@code BigDecimal} number with the specified value, forming a
  148.50 + * {@link MathContext} object with the proper settings
  148.51 + * ({@code precision} set to {@code 1}, and the
  148.52 + * {@code roundingMode} set to the rounding mode in question), and
  148.53 + * calling {@link BigDecimal#round round} on this number with the
  148.54 + * proper {@code MathContext}.  A summary table showing the results
  148.55 + * of these rounding operations for all rounding modes appears below.
  148.56 + *
  148.57 + *<p>
  148.58 + *<table border>
  148.59 + * <caption><b>Summary of Rounding Operations Under Different Rounding Modes</b></caption>
  148.60 + * <tr><th></th><th colspan=8>Result of rounding input to one digit with the given
  148.61 + *                           rounding mode</th>
  148.62 + * <tr valign=top>
  148.63 + * <th>Input Number</th>         <th>{@code UP}</th>
  148.64 + *                                           <th>{@code DOWN}</th>
  148.65 + *                                                        <th>{@code CEILING}</th>
  148.66 + *                                                                       <th>{@code FLOOR}</th>
  148.67 + *                                                                                    <th>{@code HALF_UP}</th>
  148.68 + *                                                                                                   <th>{@code HALF_DOWN}</th>
  148.69 + *                                                                                                                    <th>{@code HALF_EVEN}</th>
  148.70 + *                                                                                                                                     <th>{@code UNNECESSARY}</th>
  148.71 + *
  148.72 + * <tr align=right><td>5.5</td>  <td>6</td>  <td>5</td>    <td>6</td>    <td>5</td>  <td>6</td>      <td>5</td>       <td>6</td>       <td>throw {@code ArithmeticException}</td>
  148.73 + * <tr align=right><td>2.5</td>  <td>3</td>  <td>2</td>    <td>3</td>    <td>2</td>  <td>3</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
  148.74 + * <tr align=right><td>1.6</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>2</td>      <td>2</td>       <td>2</td>       <td>throw {@code ArithmeticException}</td>
  148.75 + * <tr align=right><td>1.1</td>  <td>2</td>  <td>1</td>    <td>2</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>throw {@code ArithmeticException}</td>
  148.76 + * <tr align=right><td>1.0</td>  <td>1</td>  <td>1</td>    <td>1</td>    <td>1</td>  <td>1</td>      <td>1</td>       <td>1</td>       <td>1</td>
  148.77 + * <tr align=right><td>-1.0</td> <td>-1</td> <td>-1</td>   <td>-1</td>   <td>-1</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>-1</td>
  148.78 + * <tr align=right><td>-1.1</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-1</td>     <td>-1</td>      <td>-1</td>      <td>throw {@code ArithmeticException}</td>
  148.79 + * <tr align=right><td>-1.6</td> <td>-2</td> <td>-1</td>   <td>-1</td>   <td>-2</td> <td>-2</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
  148.80 + * <tr align=right><td>-2.5</td> <td>-3</td> <td>-2</td>   <td>-2</td>   <td>-3</td> <td>-3</td>     <td>-2</td>      <td>-2</td>      <td>throw {@code ArithmeticException}</td>
  148.81 + * <tr align=right><td>-5.5</td> <td>-6</td> <td>-5</td>   <td>-5</td>   <td>-6</td> <td>-6</td>     <td>-5</td>      <td>-6</td>      <td>throw {@code ArithmeticException}</td>
  148.82 + *</table>
  148.83 + *
  148.84 + *
  148.85 + * <p>This {@code enum} is intended to replace the integer-based
  148.86 + * enumeration of rounding mode constants in {@link BigDecimal}
  148.87 + * ({@link BigDecimal#ROUND_UP}, {@link BigDecimal#ROUND_DOWN},
  148.88 + * etc. ).
  148.89 + *
  148.90 + * @see     BigDecimal
  148.91 + * @see     MathContext
  148.92 + * @author  Josh Bloch
  148.93 + * @author  Mike Cowlishaw
  148.94 + * @author  Joseph D. Darcy
  148.95 + * @since 1.5
  148.96 + */
  148.97 +public enum RoundingMode {
  148.98 +
  148.99 +        /**
 148.100 +         * Rounding mode to round away from zero.  Always increments the
 148.101 +         * digit prior to a non-zero discarded fraction.  Note that this
 148.102 +         * rounding mode never decreases the magnitude of the calculated
 148.103 +         * value.
 148.104 +         *
 148.105 +         *<p>Example:
 148.106 +         *<table border>
 148.107 +         *<tr valign=top><th>Input Number</th>
 148.108 +         *    <th>Input rounded to one digit<br> with {@code UP} rounding
 148.109 +         *<tr align=right><td>5.5</td>  <td>6</td>
 148.110 +         *<tr align=right><td>2.5</td>  <td>3</td>
 148.111 +         *<tr align=right><td>1.6</td>  <td>2</td>
 148.112 +         *<tr align=right><td>1.1</td>  <td>2</td>
 148.113 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.114 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.115 +         *<tr align=right><td>-1.1</td> <td>-2</td>
 148.116 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 148.117 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 148.118 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 148.119 +         *</table>
 148.120 +         */
 148.121 +    UP(BigDecimal.ROUND_UP),
 148.122 +
 148.123 +        /**
 148.124 +         * Rounding mode to round towards zero.  Never increments the digit
 148.125 +         * prior to a discarded fraction (i.e., truncates).  Note that this
 148.126 +         * rounding mode never increases the magnitude of the calculated value.
 148.127 +         *
 148.128 +         *<p>Example:
 148.129 +         *<table border>
 148.130 +         *<tr valign=top><th>Input Number</th>
 148.131 +         *    <th>Input rounded to one digit<br> with {@code DOWN} rounding
 148.132 +         *<tr align=right><td>5.5</td>  <td>5</td>
 148.133 +         *<tr align=right><td>2.5</td>  <td>2</td>
 148.134 +         *<tr align=right><td>1.6</td>  <td>1</td>
 148.135 +         *<tr align=right><td>1.1</td>  <td>1</td>
 148.136 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.137 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.138 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 148.139 +         *<tr align=right><td>-1.6</td> <td>-1</td>
 148.140 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 148.141 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 148.142 +         *</table>
 148.143 +         */
 148.144 +    DOWN(BigDecimal.ROUND_DOWN),
 148.145 +
 148.146 +        /**
 148.147 +         * Rounding mode to round towards positive infinity.  If the
 148.148 +         * result is positive, behaves as for {@code RoundingMode.UP};
 148.149 +         * if negative, behaves as for {@code RoundingMode.DOWN}.  Note
 148.150 +         * that this rounding mode never decreases the calculated value.
 148.151 +         *
 148.152 +         *<p>Example:
 148.153 +         *<table border>
 148.154 +         *<tr valign=top><th>Input Number</th>
 148.155 +         *    <th>Input rounded to one digit<br> with {@code CEILING} rounding
 148.156 +         *<tr align=right><td>5.5</td>  <td>6</td>
 148.157 +         *<tr align=right><td>2.5</td>  <td>3</td>
 148.158 +         *<tr align=right><td>1.6</td>  <td>2</td>
 148.159 +         *<tr align=right><td>1.1</td>  <td>2</td>
 148.160 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.161 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.162 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 148.163 +         *<tr align=right><td>-1.6</td> <td>-1</td>
 148.164 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 148.165 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 148.166 +         *</table>
 148.167 +         */
 148.168 +    CEILING(BigDecimal.ROUND_CEILING),
 148.169 +
 148.170 +        /**
 148.171 +         * Rounding mode to round towards negative infinity.  If the
 148.172 +         * result is positive, behave as for {@code RoundingMode.DOWN};
 148.173 +         * if negative, behave as for {@code RoundingMode.UP}.  Note that
 148.174 +         * this rounding mode never increases the calculated value.
 148.175 +         *
 148.176 +         *<p>Example:
 148.177 +         *<table border>
 148.178 +         *<tr valign=top><th>Input Number</th>
 148.179 +         *    <th>Input rounded to one digit<br> with {@code FLOOR} rounding
 148.180 +         *<tr align=right><td>5.5</td>  <td>5</td>
 148.181 +         *<tr align=right><td>2.5</td>  <td>2</td>
 148.182 +         *<tr align=right><td>1.6</td>  <td>1</td>
 148.183 +         *<tr align=right><td>1.1</td>  <td>1</td>
 148.184 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.185 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.186 +         *<tr align=right><td>-1.1</td> <td>-2</td>
 148.187 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 148.188 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 148.189 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 148.190 +         *</table>
 148.191 +         */
 148.192 +    FLOOR(BigDecimal.ROUND_FLOOR),
 148.193 +
 148.194 +        /**
 148.195 +         * Rounding mode to round towards {@literal "nearest neighbor"}
 148.196 +         * unless both neighbors are equidistant, in which case round up.
 148.197 +         * Behaves as for {@code RoundingMode.UP} if the discarded
 148.198 +         * fraction is &ge; 0.5; otherwise, behaves as for
 148.199 +         * {@code RoundingMode.DOWN}.  Note that this is the rounding
 148.200 +         * mode commonly taught at school.
 148.201 +         *
 148.202 +         *<p>Example:
 148.203 +         *<table border>
 148.204 +         *<tr valign=top><th>Input Number</th>
 148.205 +         *    <th>Input rounded to one digit<br> with {@code HALF_UP} rounding
 148.206 +         *<tr align=right><td>5.5</td>  <td>6</td>
 148.207 +         *<tr align=right><td>2.5</td>  <td>3</td>
 148.208 +         *<tr align=right><td>1.6</td>  <td>2</td>
 148.209 +         *<tr align=right><td>1.1</td>  <td>1</td>
 148.210 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.211 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.212 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 148.213 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 148.214 +         *<tr align=right><td>-2.5</td> <td>-3</td>
 148.215 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 148.216 +         *</table>
 148.217 +         */
 148.218 +    HALF_UP(BigDecimal.ROUND_HALF_UP),
 148.219 +
 148.220 +        /**
 148.221 +         * Rounding mode to round towards {@literal "nearest neighbor"}
 148.222 +         * unless both neighbors are equidistant, in which case round
 148.223 +         * down.  Behaves as for {@code RoundingMode.UP} if the discarded
 148.224 +         * fraction is &gt; 0.5; otherwise, behaves as for
 148.225 +         * {@code RoundingMode.DOWN}.
 148.226 +         *
 148.227 +         *<p>Example:
 148.228 +         *<table border>
 148.229 +         *<tr valign=top><th>Input Number</th>
 148.230 +         *    <th>Input rounded to one digit<br> with {@code HALF_DOWN} rounding
 148.231 +         *<tr align=right><td>5.5</td>  <td>5</td>
 148.232 +         *<tr align=right><td>2.5</td>  <td>2</td>
 148.233 +         *<tr align=right><td>1.6</td>  <td>2</td>
 148.234 +         *<tr align=right><td>1.1</td>  <td>1</td>
 148.235 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.236 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.237 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 148.238 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 148.239 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 148.240 +         *<tr align=right><td>-5.5</td> <td>-5</td>
 148.241 +         *</table>
 148.242 +         */
 148.243 +    HALF_DOWN(BigDecimal.ROUND_HALF_DOWN),
 148.244 +
 148.245 +        /**
 148.246 +         * Rounding mode to round towards the {@literal "nearest neighbor"}
 148.247 +         * unless both neighbors are equidistant, in which case, round
 148.248 +         * towards the even neighbor.  Behaves as for
 148.249 +         * {@code RoundingMode.HALF_UP} if the digit to the left of the
 148.250 +         * discarded fraction is odd; behaves as for
 148.251 +         * {@code RoundingMode.HALF_DOWN} if it's even.  Note that this
 148.252 +         * is the rounding mode that statistically minimizes cumulative
 148.253 +         * error when applied repeatedly over a sequence of calculations.
 148.254 +         * It is sometimes known as {@literal "Banker's rounding,"} and is
 148.255 +         * chiefly used in the USA.  This rounding mode is analogous to
 148.256 +         * the rounding policy used for {@code float} and {@code double}
 148.257 +         * arithmetic in Java.
 148.258 +         *
 148.259 +         *<p>Example:
 148.260 +         *<table border>
 148.261 +         *<tr valign=top><th>Input Number</th>
 148.262 +         *    <th>Input rounded to one digit<br> with {@code HALF_EVEN} rounding
 148.263 +         *<tr align=right><td>5.5</td>  <td>6</td>
 148.264 +         *<tr align=right><td>2.5</td>  <td>2</td>
 148.265 +         *<tr align=right><td>1.6</td>  <td>2</td>
 148.266 +         *<tr align=right><td>1.1</td>  <td>1</td>
 148.267 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.268 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.269 +         *<tr align=right><td>-1.1</td> <td>-1</td>
 148.270 +         *<tr align=right><td>-1.6</td> <td>-2</td>
 148.271 +         *<tr align=right><td>-2.5</td> <td>-2</td>
 148.272 +         *<tr align=right><td>-5.5</td> <td>-6</td>
 148.273 +         *</table>
 148.274 +         */
 148.275 +    HALF_EVEN(BigDecimal.ROUND_HALF_EVEN),
 148.276 +
 148.277 +        /**
 148.278 +         * Rounding mode to assert that the requested operation has an exact
 148.279 +         * result, hence no rounding is necessary.  If this rounding mode is
 148.280 +         * specified on an operation that yields an inexact result, an
 148.281 +         * {@code ArithmeticException} is thrown.
 148.282 +         *<p>Example:
 148.283 +         *<table border>
 148.284 +         *<tr valign=top><th>Input Number</th>
 148.285 +         *    <th>Input rounded to one digit<br> with {@code UNNECESSARY} rounding
 148.286 +         *<tr align=right><td>5.5</td>  <td>throw {@code ArithmeticException}</td>
 148.287 +         *<tr align=right><td>2.5</td>  <td>throw {@code ArithmeticException}</td>
 148.288 +         *<tr align=right><td>1.6</td>  <td>throw {@code ArithmeticException}</td>
 148.289 +         *<tr align=right><td>1.1</td>  <td>throw {@code ArithmeticException}</td>
 148.290 +         *<tr align=right><td>1.0</td>  <td>1</td>
 148.291 +         *<tr align=right><td>-1.0</td> <td>-1</td>
 148.292 +         *<tr align=right><td>-1.1</td> <td>throw {@code ArithmeticException}</td>
 148.293 +         *<tr align=right><td>-1.6</td> <td>throw {@code ArithmeticException}</td>
 148.294 +         *<tr align=right><td>-2.5</td> <td>throw {@code ArithmeticException}</td>
 148.295 +         *<tr align=right><td>-5.5</td> <td>throw {@code ArithmeticException}</td>
 148.296 +         *</table>
 148.297 +         */
 148.298 +    UNNECESSARY(BigDecimal.ROUND_UNNECESSARY);
 148.299 +
 148.300 +    // Corresponding BigDecimal rounding constant
 148.301 +    final int oldMode;
 148.302 +
 148.303 +    /**
 148.304 +     * Constructor
 148.305 +     *
 148.306 +     * @param oldMode The {@code BigDecimal} constant corresponding to
 148.307 +     *        this mode
 148.308 +     */
 148.309 +    private RoundingMode(int oldMode) {
 148.310 +        this.oldMode = oldMode;
 148.311 +    }
 148.312 +
 148.313 +    /**
 148.314 +     * Returns the {@code RoundingMode} object corresponding to a
 148.315 +     * legacy integer rounding mode constant in {@link BigDecimal}.
 148.316 +     *
 148.317 +     * @param  rm legacy integer rounding mode to convert
 148.318 +     * @return {@code RoundingMode} corresponding to the given integer.
 148.319 +     * @throws IllegalArgumentException integer is out of range
 148.320 +     */
 148.321 +    public static RoundingMode valueOf(int rm) {
 148.322 +        switch(rm) {
 148.323 +
 148.324 +        case BigDecimal.ROUND_UP:
 148.325 +            return UP;
 148.326 +
 148.327 +        case BigDecimal.ROUND_DOWN:
 148.328 +            return DOWN;
 148.329 +
 148.330 +        case BigDecimal.ROUND_CEILING:
 148.331 +            return CEILING;
 148.332 +
 148.333 +        case BigDecimal.ROUND_FLOOR:
 148.334 +            return FLOOR;
 148.335 +
 148.336 +        case BigDecimal.ROUND_HALF_UP:
 148.337 +            return HALF_UP;
 148.338 +
 148.339 +        case BigDecimal.ROUND_HALF_DOWN:
 148.340 +            return HALF_DOWN;
 148.341 +
 148.342 +        case BigDecimal.ROUND_HALF_EVEN:
 148.343 +            return HALF_EVEN;
 148.344 +
 148.345 +        case BigDecimal.ROUND_UNNECESSARY:
 148.346 +            return UNNECESSARY;
 148.347 +
 148.348 +        default:
 148.349 +            throw new IllegalArgumentException("argument out of range");
 148.350 +        }
 148.351 +    }
 148.352 +}
   149.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   149.2 +++ b/rt/emul/compact/src/main/java/java/math/SignedMutableBigInteger.java	Mon Oct 07 14:20:58 2013 +0200
   149.3 @@ -0,0 +1,135 @@
   149.4 +/*
   149.5 + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved.
   149.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   149.7 + *
   149.8 + * This code is free software; you can redistribute it and/or modify it
   149.9 + * under the terms of the GNU General Public License version 2 only, as
  149.10 + * published by the Free Software Foundation.  Oracle designates this
  149.11 + * particular file as subject to the "Classpath" exception as provided
  149.12 + * by Oracle in the LICENSE file that accompanied this code.
  149.13 + *
  149.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  149.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  149.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  149.17 + * version 2 for more details (a copy is included in the LICENSE file that
  149.18 + * accompanied this code).
  149.19 + *
  149.20 + * You should have received a copy of the GNU General Public License version
  149.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  149.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  149.23 + *
  149.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  149.25 + * or visit www.oracle.com if you need additional information or have any
  149.26 + * questions.
  149.27 + */
  149.28 +
  149.29 +package java.math;
  149.30 +
  149.31 +/**
  149.32 + * A class used to represent multiprecision integers that makes efficient
  149.33 + * use of allocated space by allowing a number to occupy only part of
  149.34 + * an array so that the arrays do not have to be reallocated as often.
  149.35 + * When performing an operation with many iterations the array used to
  149.36 + * hold a number is only increased when necessary and does not have to
  149.37 + * be the same size as the number it represents. A mutable number allows
  149.38 + * calculations to occur on the same number without having to create
  149.39 + * a new number for every step of the calculation as occurs with
  149.40 + * BigIntegers.
  149.41 + *
  149.42 + * Note that SignedMutableBigIntegers only support signed addition and
  149.43 + * subtraction. All other operations occur as with MutableBigIntegers.
  149.44 + *
  149.45 + * @see     BigInteger
  149.46 + * @author  Michael McCloskey
  149.47 + * @since   1.3
  149.48 + */
  149.49 +
  149.50 +class SignedMutableBigInteger extends MutableBigInteger {
  149.51 +
  149.52 +   /**
  149.53 +     * The sign of this MutableBigInteger.
  149.54 +     */
  149.55 +    int sign = 1;
  149.56 +
  149.57 +    // Constructors
  149.58 +
  149.59 +    /**
  149.60 +     * The default constructor. An empty MutableBigInteger is created with
  149.61 +     * a one word capacity.
  149.62 +     */
  149.63 +    SignedMutableBigInteger() {
  149.64 +        super();
  149.65 +    }
  149.66 +
  149.67 +    /**
  149.68 +     * Construct a new MutableBigInteger with a magnitude specified by
  149.69 +     * the int val.
  149.70 +     */
  149.71 +    SignedMutableBigInteger(int val) {
  149.72 +        super(val);
  149.73 +    }
  149.74 +
  149.75 +    /**
  149.76 +     * Construct a new MutableBigInteger with a magnitude equal to the
  149.77 +     * specified MutableBigInteger.
  149.78 +     */
  149.79 +    SignedMutableBigInteger(MutableBigInteger val) {
  149.80 +        super(val);
  149.81 +    }
  149.82 +
  149.83 +   // Arithmetic Operations
  149.84 +
  149.85 +   /**
  149.86 +     * Signed addition built upon unsigned add and subtract.
  149.87 +     */
  149.88 +    void signedAdd(SignedMutableBigInteger addend) {
  149.89 +        if (sign == addend.sign)
  149.90 +            add(addend);
  149.91 +        else
  149.92 +            sign = sign * subtract(addend);
  149.93 +
  149.94 +    }
  149.95 +
  149.96 +   /**
  149.97 +     * Signed addition built upon unsigned add and subtract.
  149.98 +     */
  149.99 +    void signedAdd(MutableBigInteger addend) {
 149.100 +        if (sign == 1)
 149.101 +            add(addend);
 149.102 +        else
 149.103 +            sign = sign * subtract(addend);
 149.104 +
 149.105 +    }
 149.106 +
 149.107 +   /**
 149.108 +     * Signed subtraction built upon unsigned add and subtract.
 149.109 +     */
 149.110 +    void signedSubtract(SignedMutableBigInteger addend) {
 149.111 +        if (sign == addend.sign)
 149.112 +            sign = sign * subtract(addend);
 149.113 +        else
 149.114 +            add(addend);
 149.115 +
 149.116 +    }
 149.117 +
 149.118 +   /**
 149.119 +     * Signed subtraction built upon unsigned add and subtract.
 149.120 +     */
 149.121 +    void signedSubtract(MutableBigInteger addend) {
 149.122 +        if (sign == 1)
 149.123 +            sign = sign * subtract(addend);
 149.124 +        else
 149.125 +            add(addend);
 149.126 +        if (intLen == 0)
 149.127 +             sign = 1;
 149.128 +    }
 149.129 +
 149.130 +    /**
 149.131 +     * Print out the first intLen ints of this MutableBigInteger's value
 149.132 +     * array starting at offset.
 149.133 +     */
 149.134 +    public String toString() {
 149.135 +        return this.toBigInteger(sign).toString();
 149.136 +    }
 149.137 +
 149.138 +}
   150.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   150.2 +++ b/rt/emul/compact/src/main/java/java/math/package-info.java	Mon Oct 07 14:20:58 2013 +0200
   150.3 @@ -0,0 +1,45 @@
   150.4 +/*
   150.5 + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved.
   150.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   150.7 + *
   150.8 + * This code is free software; you can redistribute it and/or modify it
   150.9 + * under the terms of the GNU General Public License version 2 only, as
  150.10 + * published by the Free Software Foundation.  Oracle designates this
  150.11 + * particular file as subject to the "Classpath" exception as provided
  150.12 + * by Oracle in the LICENSE file that accompanied this code.
  150.13 + *
  150.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  150.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  150.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  150.17 + * version 2 for more details (a copy is included in the LICENSE file that
  150.18 + * accompanied this code).
  150.19 + *
  150.20 + * You should have received a copy of the GNU General Public License version
  150.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  150.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  150.23 + *
  150.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  150.25 + * or visit www.oracle.com if you need additional information or have any
  150.26 + * questions.
  150.27 + */
  150.28 +
  150.29 +/**
  150.30 + * Provides classes for performing arbitrary-precision integer
  150.31 + * arithmetic ({@code BigInteger}) and arbitrary-precision decimal
  150.32 + * arithmetic ({@code BigDecimal}).  {@code BigInteger} is analogous
  150.33 + * to the primitive integer types except that it provides arbitrary
  150.34 + * precision, hence operations on {@code BigInteger}s do not overflow
  150.35 + * or lose precision.  In addition to standard arithmetic operations,
  150.36 + * {@code BigInteger} provides modular arithmetic, GCD calculation,
  150.37 + * primality testing, prime generation, bit manipulation, and a few
  150.38 + * other miscellaneous operations.
  150.39 + *
  150.40 + * {@code BigDecimal} provides arbitrary-precision signed decimal
  150.41 + * numbers suitable for currency calculations and the like.  {@code
  150.42 + * BigDecimal} gives the user complete control over rounding behavior,
  150.43 + * allowing the user to choose from a comprehensive set of eight
  150.44 + * rounding modes.
  150.45 + *
  150.46 + * @since JDK1.1
  150.47 + */
  150.48 +package java.math;
   151.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   151.2 +++ b/rt/emul/compact/src/main/java/java/net/URI.java	Mon Oct 07 14:20:58 2013 +0200
   151.3 @@ -0,0 +1,3520 @@
   151.4 +/*
   151.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   151.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   151.7 + *
   151.8 + * This code is free software; you can redistribute it and/or modify it
   151.9 + * under the terms of the GNU General Public License version 2 only, as
  151.10 + * published by the Free Software Foundation.  Oracle designates this
  151.11 + * particular file as subject to the "Classpath" exception as provided
  151.12 + * by Oracle in the LICENSE file that accompanied this code.
  151.13 + *
  151.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  151.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  151.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  151.17 + * version 2 for more details (a copy is included in the LICENSE file that
  151.18 + * accompanied this code).
  151.19 + *
  151.20 + * You should have received a copy of the GNU General Public License version
  151.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  151.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  151.23 + *
  151.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  151.25 + * or visit www.oracle.com if you need additional information or have any
  151.26 + * questions.
  151.27 + */
  151.28 +
  151.29 +package java.net;
  151.30 +
  151.31 +import java.io.IOException;
  151.32 +import java.io.InvalidObjectException;
  151.33 +import java.io.ObjectInputStream;
  151.34 +import java.io.ObjectOutputStream;
  151.35 +import java.io.Serializable;
  151.36 +
  151.37 +import java.lang.Character;             // for javadoc
  151.38 +import java.lang.NullPointerException;  // for javadoc
  151.39 +
  151.40 +
  151.41 +/**
  151.42 + * Represents a Uniform Resource Identifier (URI) reference.
  151.43 + *
  151.44 + * <p> Aside from some minor deviations noted below, an instance of this
  151.45 + * class represents a URI reference as defined by
  151.46 + * <a href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
  151.47 + * Resource Identifiers (URI): Generic Syntax</i></a>, amended by <a
  151.48 + * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
  151.49 + * Literal IPv6 Addresses in URLs</i></a>. The Literal IPv6 address format
  151.50 + * also supports scope_ids. The syntax and usage of scope_ids is described
  151.51 + * <a href="Inet6Address.html#scoped">here</a>.
  151.52 + * This class provides constructors for creating URI instances from
  151.53 + * their components or by parsing their string forms, methods for accessing the
  151.54 + * various components of an instance, and methods for normalizing, resolving,
  151.55 + * and relativizing URI instances.  Instances of this class are immutable.
  151.56 + *
  151.57 + *
  151.58 + * <h4> URI syntax and components </h4>
  151.59 + *
  151.60 + * At the highest level a URI reference (hereinafter simply "URI") in string
  151.61 + * form has the syntax
  151.62 + *
  151.63 + * <blockquote>
  151.64 + * [<i>scheme</i><tt><b>:</b></tt><i></i>]<i>scheme-specific-part</i>[<tt><b>#</b></tt><i>fragment</i>]
  151.65 + * </blockquote>
  151.66 + *
  151.67 + * where square brackets [...] delineate optional components and the characters
  151.68 + * <tt><b>:</b></tt> and <tt><b>#</b></tt> stand for themselves.
  151.69 + *
  151.70 + * <p> An <i>absolute</i> URI specifies a scheme; a URI that is not absolute is
  151.71 + * said to be <i>relative</i>.  URIs are also classified according to whether
  151.72 + * they are <i>opaque</i> or <i>hierarchical</i>.
  151.73 + *
  151.74 + * <p> An <i>opaque</i> URI is an absolute URI whose scheme-specific part does
  151.75 + * not begin with a slash character (<tt>'/'</tt>).  Opaque URIs are not
  151.76 + * subject to further parsing.  Some examples of opaque URIs are:
  151.77 + *
  151.78 + * <blockquote><table cellpadding=0 cellspacing=0 summary="layout">
  151.79 + * <tr><td><tt>mailto:java-net@java.sun.com</tt><td></tr>
  151.80 + * <tr><td><tt>news:comp.lang.java</tt><td></tr>
  151.81 + * <tr><td><tt>urn:isbn:096139210x</tt></td></tr>
  151.82 + * </table></blockquote>
  151.83 + *
  151.84 + * <p> A <i>hierarchical</i> URI is either an absolute URI whose
  151.85 + * scheme-specific part begins with a slash character, or a relative URI, that
  151.86 + * is, a URI that does not specify a scheme.  Some examples of hierarchical
  151.87 + * URIs are:
  151.88 + *
  151.89 + * <blockquote>
  151.90 + * <tt>http://java.sun.com/j2se/1.3/</tt><br>
  151.91 + * <tt>docs/guide/collections/designfaq.html#28</tt><br>
  151.92 + * <tt>../../../demo/jfc/SwingSet2/src/SwingSet2.java</tt><br>
  151.93 + * <tt>file:///~/calendar</tt>
  151.94 + * </blockquote>
  151.95 + *
  151.96 + * <p> A hierarchical URI is subject to further parsing according to the syntax
  151.97 + *
  151.98 + * <blockquote>
  151.99 + * [<i>scheme</i><tt><b>:</b></tt>][<tt><b>//</b></tt><i>authority</i>][<i>path</i>][<tt><b>?</b></tt><i>query</i>][<tt><b>#</b></tt><i>fragment</i>]
 151.100 + * </blockquote>
 151.101 + *
 151.102 + * where the characters <tt><b>:</b></tt>, <tt><b>/</b></tt>,
 151.103 + * <tt><b>?</b></tt>, and <tt><b>#</b></tt> stand for themselves.  The
 151.104 + * scheme-specific part of a hierarchical URI consists of the characters
 151.105 + * between the scheme and fragment components.
 151.106 + *
 151.107 + * <p> The authority component of a hierarchical URI is, if specified, either
 151.108 + * <i>server-based</i> or <i>registry-based</i>.  A server-based authority
 151.109 + * parses according to the familiar syntax
 151.110 + *
 151.111 + * <blockquote>
 151.112 + * [<i>user-info</i><tt><b>@</b></tt>]<i>host</i>[<tt><b>:</b></tt><i>port</i>]
 151.113 + * </blockquote>
 151.114 + *
 151.115 + * where the characters <tt><b>@</b></tt> and <tt><b>:</b></tt> stand for
 151.116 + * themselves.  Nearly all URI schemes currently in use are server-based.  An
 151.117 + * authority component that does not parse in this way is considered to be
 151.118 + * registry-based.
 151.119 + *
 151.120 + * <p> The path component of a hierarchical URI is itself said to be absolute
 151.121 + * if it begins with a slash character (<tt>'/'</tt>); otherwise it is
 151.122 + * relative.  The path of a hierarchical URI that is either absolute or
 151.123 + * specifies an authority is always absolute.
 151.124 + *
 151.125 + * <p> All told, then, a URI instance has the following nine components:
 151.126 + *
 151.127 + * <blockquote><table summary="Describes the components of a URI:scheme,scheme-specific-part,authority,user-info,host,port,path,query,fragment">
 151.128 + * <tr><th><i>Component</i></th><th><i>Type</i></th></tr>
 151.129 + * <tr><td>scheme</td><td><tt>String</tt></td></tr>
 151.130 + * <tr><td>scheme-specific-part&nbsp;&nbsp;&nbsp;&nbsp;</td><td><tt>String</tt></td></tr>
 151.131 + * <tr><td>authority</td><td><tt>String</tt></td></tr>
 151.132 + * <tr><td>user-info</td><td><tt>String</tt></td></tr>
 151.133 + * <tr><td>host</td><td><tt>String</tt></td></tr>
 151.134 + * <tr><td>port</td><td><tt>int</tt></td></tr>
 151.135 + * <tr><td>path</td><td><tt>String</tt></td></tr>
 151.136 + * <tr><td>query</td><td><tt>String</tt></td></tr>
 151.137 + * <tr><td>fragment</td><td><tt>String</tt></td></tr>
 151.138 + * </table></blockquote>
 151.139 + *
 151.140 + * In a given instance any particular component is either <i>undefined</i> or
 151.141 + * <i>defined</i> with a distinct value.  Undefined string components are
 151.142 + * represented by <tt>null</tt>, while undefined integer components are
 151.143 + * represented by <tt>-1</tt>.  A string component may be defined to have the
 151.144 + * empty string as its value; this is not equivalent to that component being
 151.145 + * undefined.
 151.146 + *
 151.147 + * <p> Whether a particular component is or is not defined in an instance
 151.148 + * depends upon the type of the URI being represented.  An absolute URI has a
 151.149 + * scheme component.  An opaque URI has a scheme, a scheme-specific part, and
 151.150 + * possibly a fragment, but has no other components.  A hierarchical URI always
 151.151 + * has a path (though it may be empty) and a scheme-specific-part (which at
 151.152 + * least contains the path), and may have any of the other components.  If the
 151.153 + * authority component is present and is server-based then the host component
 151.154 + * will be defined and the user-information and port components may be defined.
 151.155 + *
 151.156 + *
 151.157 + * <h4> Operations on URI instances </h4>
 151.158 + *
 151.159 + * The key operations supported by this class are those of
 151.160 + * <i>normalization</i>, <i>resolution</i>, and <i>relativization</i>.
 151.161 + *
 151.162 + * <p> <i>Normalization</i> is the process of removing unnecessary <tt>"."</tt>
 151.163 + * and <tt>".."</tt> segments from the path component of a hierarchical URI.
 151.164 + * Each <tt>"."</tt> segment is simply removed.  A <tt>".."</tt> segment is
 151.165 + * removed only if it is preceded by a non-<tt>".."</tt> segment.
 151.166 + * Normalization has no effect upon opaque URIs.
 151.167 + *
 151.168 + * <p> <i>Resolution</i> is the process of resolving one URI against another,
 151.169 + * <i>base</i> URI.  The resulting URI is constructed from components of both
 151.170 + * URIs in the manner specified by RFC&nbsp;2396, taking components from the
 151.171 + * base URI for those not specified in the original.  For hierarchical URIs,
 151.172 + * the path of the original is resolved against the path of the base and then
 151.173 + * normalized.  The result, for example, of resolving
 151.174 + *
 151.175 + * <blockquote>
 151.176 + * <tt>docs/guide/collections/designfaq.html#28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt>(1)
 151.177 + * </blockquote>
 151.178 + *
 151.179 + * against the base URI <tt>http://java.sun.com/j2se/1.3/</tt> is the result
 151.180 + * URI
 151.181 + *
 151.182 + * <blockquote>
 151.183 + * <tt>http://java.sun.com/j2se/1.3/docs/guide/collections/designfaq.html#28</tt>
 151.184 + * </blockquote>
 151.185 + *
 151.186 + * Resolving the relative URI
 151.187 + *
 151.188 + * <blockquote>
 151.189 + * <tt>../../../demo/jfc/SwingSet2/src/SwingSet2.java&nbsp;&nbsp;&nbsp;&nbsp;</tt>(2)
 151.190 + * </blockquote>
 151.191 + *
 151.192 + * against this result yields, in turn,
 151.193 + *
 151.194 + * <blockquote>
 151.195 + * <tt>http://java.sun.com/j2se/1.3/demo/jfc/SwingSet2/src/SwingSet2.java</tt>
 151.196 + * </blockquote>
 151.197 + *
 151.198 + * Resolution of both absolute and relative URIs, and of both absolute and
 151.199 + * relative paths in the case of hierarchical URIs, is supported.  Resolving
 151.200 + * the URI <tt>file:///~calendar</tt> against any other URI simply yields the
 151.201 + * original URI, since it is absolute.  Resolving the relative URI (2) above
 151.202 + * against the relative base URI (1) yields the normalized, but still relative,
 151.203 + * URI
 151.204 + *
 151.205 + * <blockquote>
 151.206 + * <tt>demo/jfc/SwingSet2/src/SwingSet2.java</tt>
 151.207 + * </blockquote>
 151.208 + *
 151.209 + * <p> <i>Relativization</i>, finally, is the inverse of resolution: For any
 151.210 + * two normalized URIs <i>u</i> and&nbsp;<i>v</i>,
 151.211 + *
 151.212 + * <blockquote>
 151.213 + *   <i>u</i><tt>.relativize(</tt><i>u</i><tt>.resolve(</tt><i>v</i><tt>)).equals(</tt><i>v</i><tt>)</tt>&nbsp;&nbsp;and<br>
 151.214 + *   <i>u</i><tt>.resolve(</tt><i>u</i><tt>.relativize(</tt><i>v</i><tt>)).equals(</tt><i>v</i><tt>)</tt>&nbsp;&nbsp;.<br>
 151.215 + * </blockquote>
 151.216 + *
 151.217 + * This operation is often useful when constructing a document containing URIs
 151.218 + * that must be made relative to the base URI of the document wherever
 151.219 + * possible.  For example, relativizing the URI
 151.220 + *
 151.221 + * <blockquote>
 151.222 + * <tt>http://java.sun.com/j2se/1.3/docs/guide/index.html</tt>
 151.223 + * </blockquote>
 151.224 + *
 151.225 + * against the base URI
 151.226 + *
 151.227 + * <blockquote>
 151.228 + * <tt>http://java.sun.com/j2se/1.3</tt>
 151.229 + * </blockquote>
 151.230 + *
 151.231 + * yields the relative URI <tt>docs/guide/index.html</tt>.
 151.232 + *
 151.233 + *
 151.234 + * <h4> Character categories </h4>
 151.235 + *
 151.236 + * RFC&nbsp;2396 specifies precisely which characters are permitted in the
 151.237 + * various components of a URI reference.  The following categories, most of
 151.238 + * which are taken from that specification, are used below to describe these
 151.239 + * constraints:
 151.240 + *
 151.241 + * <blockquote><table cellspacing=2 summary="Describes categories alpha,digit,alphanum,unreserved,punct,reserved,escaped,and other">
 151.242 + *   <tr><th valign=top><i>alpha</i></th>
 151.243 + *       <td>The US-ASCII alphabetic characters,
 151.244 + *        <tt>'A'</tt>&nbsp;through&nbsp;<tt>'Z'</tt>
 151.245 + *        and <tt>'a'</tt>&nbsp;through&nbsp;<tt>'z'</tt></td></tr>
 151.246 + *   <tr><th valign=top><i>digit</i></th>
 151.247 + *       <td>The US-ASCII decimal digit characters,
 151.248 + *       <tt>'0'</tt>&nbsp;through&nbsp;<tt>'9'</tt></td></tr>
 151.249 + *   <tr><th valign=top><i>alphanum</i></th>
 151.250 + *       <td>All <i>alpha</i> and <i>digit</i> characters</td></tr>
 151.251 + *   <tr><th valign=top><i>unreserved</i>&nbsp;&nbsp;&nbsp;&nbsp;</th>
 151.252 + *       <td>All <i>alphanum</i> characters together with those in the string
 151.253 + *        <tt>"_-!.~'()*"</tt></td></tr>
 151.254 + *   <tr><th valign=top><i>punct</i></th>
 151.255 + *       <td>The characters in the string <tt>",;:$&+="</tt></td></tr>
 151.256 + *   <tr><th valign=top><i>reserved</i></th>
 151.257 + *       <td>All <i>punct</i> characters together with those in the string
 151.258 + *        <tt>"?/[]@"</tt></td></tr>
 151.259 + *   <tr><th valign=top><i>escaped</i></th>
 151.260 + *       <td>Escaped octets, that is, triplets consisting of the percent
 151.261 + *           character (<tt>'%'</tt>) followed by two hexadecimal digits
 151.262 + *           (<tt>'0'</tt>-<tt>'9'</tt>, <tt>'A'</tt>-<tt>'F'</tt>, and
 151.263 + *           <tt>'a'</tt>-<tt>'f'</tt>)</td></tr>
 151.264 + *   <tr><th valign=top><i>other</i></th>
 151.265 + *       <td>The Unicode characters that are not in the US-ASCII character set,
 151.266 + *           are not control characters (according to the {@link
 151.267 + *           java.lang.Character#isISOControl(char) Character.isISOControl}
 151.268 + *           method), and are not space characters (according to the {@link
 151.269 + *           java.lang.Character#isSpaceChar(char) Character.isSpaceChar}
 151.270 + *           method)&nbsp;&nbsp;<i>(<b>Deviation from RFC 2396</b>, which is
 151.271 + *           limited to US-ASCII)</i></td></tr>
 151.272 + * </table></blockquote>
 151.273 + *
 151.274 + * <p><a name="legal-chars"></a> The set of all legal URI characters consists of
 151.275 + * the <i>unreserved</i>, <i>reserved</i>, <i>escaped</i>, and <i>other</i>
 151.276 + * characters.
 151.277 + *
 151.278 + *
 151.279 + * <h4> Escaped octets, quotation, encoding, and decoding </h4>
 151.280 + *
 151.281 + * RFC 2396 allows escaped octets to appear in the user-info, path, query, and
 151.282 + * fragment components.  Escaping serves two purposes in URIs:
 151.283 + *
 151.284 + * <ul>
 151.285 + *
 151.286 + *   <li><p> To <i>encode</i> non-US-ASCII characters when a URI is required to
 151.287 + *   conform strictly to RFC&nbsp;2396 by not containing any <i>other</i>
 151.288 + *   characters.  </p></li>
 151.289 + *
 151.290 + *   <li><p> To <i>quote</i> characters that are otherwise illegal in a
 151.291 + *   component.  The user-info, path, query, and fragment components differ
 151.292 + *   slightly in terms of which characters are considered legal and illegal.
 151.293 + *   </p></li>
 151.294 + *
 151.295 + * </ul>
 151.296 + *
 151.297 + * These purposes are served in this class by three related operations:
 151.298 + *
 151.299 + * <ul>
 151.300 + *
 151.301 + *   <li><p><a name="encode"></a> A character is <i>encoded</i> by replacing it
 151.302 + *   with the sequence of escaped octets that represent that character in the
 151.303 + *   UTF-8 character set.  The Euro currency symbol (<tt>'&#92;u20AC'</tt>),
 151.304 + *   for example, is encoded as <tt>"%E2%82%AC"</tt>.  <i>(<b>Deviation from
 151.305 + *   RFC&nbsp;2396</b>, which does not specify any particular character
 151.306 + *   set.)</i> </p></li>
 151.307 + *
 151.308 + *   <li><p><a name="quote"></a> An illegal character is <i>quoted</i> simply by
 151.309 + *   encoding it.  The space character, for example, is quoted by replacing it
 151.310 + *   with <tt>"%20"</tt>.  UTF-8 contains US-ASCII, hence for US-ASCII
 151.311 + *   characters this transformation has exactly the effect required by
 151.312 + *   RFC&nbsp;2396. </p></li>
 151.313 + *
 151.314 + *   <li><p><a name="decode"></a>
 151.315 + *   A sequence of escaped octets is <i>decoded</i> by
 151.316 + *   replacing it with the sequence of characters that it represents in the
 151.317 + *   UTF-8 character set.  UTF-8 contains US-ASCII, hence decoding has the
 151.318 + *   effect of de-quoting any quoted US-ASCII characters as well as that of
 151.319 + *   decoding any encoded non-US-ASCII characters.  If a <a
 151.320 + *   href="../nio/charset/CharsetDecoder.html#ce">decoding error</a> occurs
 151.321 + *   when decoding the escaped octets then the erroneous octets are replaced by
 151.322 + *   <tt>'&#92;uFFFD'</tt>, the Unicode replacement character.  </p></li>
 151.323 + *
 151.324 + * </ul>
 151.325 + *
 151.326 + * These operations are exposed in the constructors and methods of this class
 151.327 + * as follows:
 151.328 + *
 151.329 + * <ul>
 151.330 + *
 151.331 + *   <li><p> The {@link #URI(java.lang.String) <code>single-argument
 151.332 + *   constructor</code>} requires any illegal characters in its argument to be
 151.333 + *   quoted and preserves any escaped octets and <i>other</i> characters that
 151.334 + *   are present.  </p></li>
 151.335 + *
 151.336 + *   <li><p> The {@link
 151.337 + *   #URI(java.lang.String,java.lang.String,java.lang.String,int,java.lang.String,java.lang.String,java.lang.String)
 151.338 + *   <code>multi-argument constructors</code>} quote illegal characters as
 151.339 + *   required by the components in which they appear.  The percent character
 151.340 + *   (<tt>'%'</tt>) is always quoted by these constructors.  Any <i>other</i>
 151.341 + *   characters are preserved.  </p></li>
 151.342 + *
 151.343 + *   <li><p> The {@link #getRawUserInfo() getRawUserInfo}, {@link #getRawPath()
 151.344 + *   getRawPath}, {@link #getRawQuery() getRawQuery}, {@link #getRawFragment()
 151.345 + *   getRawFragment}, {@link #getRawAuthority() getRawAuthority}, and {@link
 151.346 + *   #getRawSchemeSpecificPart() getRawSchemeSpecificPart} methods return the
 151.347 + *   values of their corresponding components in raw form, without interpreting
 151.348 + *   any escaped octets.  The strings returned by these methods may contain
 151.349 + *   both escaped octets and <i>other</i> characters, and will not contain any
 151.350 + *   illegal characters.  </p></li>
 151.351 + *
 151.352 + *   <li><p> The {@link #getUserInfo() getUserInfo}, {@link #getPath()
 151.353 + *   getPath}, {@link #getQuery() getQuery}, {@link #getFragment()
 151.354 + *   getFragment}, {@link #getAuthority() getAuthority}, and {@link
 151.355 + *   #getSchemeSpecificPart() getSchemeSpecificPart} methods decode any escaped
 151.356 + *   octets in their corresponding components.  The strings returned by these
 151.357 + *   methods may contain both <i>other</i> characters and illegal characters,
 151.358 + *   and will not contain any escaped octets.  </p></li>
 151.359 + *
 151.360 + *   <li><p> The {@link #toString() toString} method returns a URI string with
 151.361 + *   all necessary quotation but which may contain <i>other</i> characters.
 151.362 + *   </p></li>
 151.363 + *
 151.364 + *   <li><p> The {@link #toASCIIString() toASCIIString} method returns a fully
 151.365 + *   quoted and encoded URI string that does not contain any <i>other</i>
 151.366 + *   characters.  </p></li>
 151.367 + *
 151.368 + * </ul>
 151.369 + *
 151.370 + *
 151.371 + * <h4> Identities </h4>
 151.372 + *
 151.373 + * For any URI <i>u</i>, it is always the case that
 151.374 + *
 151.375 + * <blockquote>
 151.376 + * <tt>new URI(</tt><i>u</i><tt>.toString()).equals(</tt><i>u</i><tt>)</tt>&nbsp;.
 151.377 + * </blockquote>
 151.378 + *
 151.379 + * For any URI <i>u</i> that does not contain redundant syntax such as two
 151.380 + * slashes before an empty authority (as in <tt>file:///tmp/</tt>&nbsp;) or a
 151.381 + * colon following a host name but no port (as in
 151.382 + * <tt>http://java.sun.com:</tt>&nbsp;), and that does not encode characters
 151.383 + * except those that must be quoted, the following identities also hold:
 151.384 + *
 151.385 + * <blockquote>
 151.386 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 151.387 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getSchemeSpecificPart(),<br>
 151.388 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 151.389 + * .equals(</tt><i>u</i><tt>)</tt>
 151.390 + * </blockquote>
 151.391 + *
 151.392 + * in all cases,
 151.393 + *
 151.394 + * <blockquote>
 151.395 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 151.396 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getUserInfo(),&nbsp;</tt><i>u</i><tt>.getAuthority(),<br>
 151.397 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getPath(),&nbsp;</tt><i>u</i><tt>.getQuery(),<br>
 151.398 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 151.399 + * .equals(</tt><i>u</i><tt>)</tt>
 151.400 + * </blockquote>
 151.401 + *
 151.402 + * if <i>u</i> is hierarchical, and
 151.403 + *
 151.404 + * <blockquote>
 151.405 + * <tt>new URI(</tt><i>u</i><tt>.getScheme(),<br>
 151.406 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getUserInfo(),&nbsp;</tt><i>u</i><tt>.getHost(),&nbsp;</tt><i>u</i><tt>.getPort(),<br>
 151.407 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getPath(),&nbsp;</tt><i>u</i><tt>.getQuery(),<br>
 151.408 + * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</tt><i>u</i><tt>.getFragment())<br>
 151.409 + * .equals(</tt><i>u</i><tt>)</tt>
 151.410 + * </blockquote>
 151.411 + *
 151.412 + * if <i>u</i> is hierarchical and has either no authority or a server-based
 151.413 + * authority.
 151.414 + *
 151.415 + *
 151.416 + * <h4> URIs, URLs, and URNs </h4>
 151.417 + *
 151.418 + * A URI is a uniform resource <i>identifier</i> while a URL is a uniform
 151.419 + * resource <i>locator</i>.  Hence every URL is a URI, abstractly speaking, but
 151.420 + * not every URI is a URL.  This is because there is another subcategory of
 151.421 + * URIs, uniform resource <i>names</i> (URNs), which name resources but do not
 151.422 + * specify how to locate them.  The <tt>mailto</tt>, <tt>news</tt>, and
 151.423 + * <tt>isbn</tt> URIs shown above are examples of URNs.
 151.424 + *
 151.425 + * <p> The conceptual distinction between URIs and URLs is reflected in the
 151.426 + * differences between this class and the {@link URL} class.
 151.427 + *
 151.428 + * <p> An instance of this class represents a URI reference in the syntactic
 151.429 + * sense defined by RFC&nbsp;2396.  A URI may be either absolute or relative.
 151.430 + * A URI string is parsed according to the generic syntax without regard to the
 151.431 + * scheme, if any, that it specifies.  No lookup of the host, if any, is
 151.432 + * performed, and no scheme-dependent stream handler is constructed.  Equality,
 151.433 + * hashing, and comparison are defined strictly in terms of the character
 151.434 + * content of the instance.  In other words, a URI instance is little more than
 151.435 + * a structured string that supports the syntactic, scheme-independent
 151.436 + * operations of comparison, normalization, resolution, and relativization.
 151.437 + *
 151.438 + * <p> An instance of the {@link URL} class, by contrast, represents the
 151.439 + * syntactic components of a URL together with some of the information required
 151.440 + * to access the resource that it describes.  A URL must be absolute, that is,
 151.441 + * it must always specify a scheme.  A URL string is parsed according to its
 151.442 + * scheme.  A stream handler is always established for a URL, and in fact it is
 151.443 + * impossible to create a URL instance for a scheme for which no handler is
 151.444 + * available.  Equality and hashing depend upon both the scheme and the
 151.445 + * Internet address of the host, if any; comparison is not defined.  In other
 151.446 + * words, a URL is a structured string that supports the syntactic operation of
 151.447 + * resolution as well as the network I/O operations of looking up the host and
 151.448 + * opening a connection to the specified resource.
 151.449 + *
 151.450 + *
 151.451 + * @author Mark Reinhold
 151.452 + * @since 1.4
 151.453 + *
 151.454 + * @see <a href="http://www.ietf.org/rfc/rfc2279.txt"><i>RFC&nbsp;2279: UTF-8, a
 151.455 + * transformation format of ISO 10646</i></a>, <br><a
 151.456 + * href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IPv6 Addressing
 151.457 + * Architecture</i></a>, <br><a
 151.458 + * href="http://www.ietf.org/rfc/rfc2396.txt"><i>RFC&nbsp;2396: Uniform
 151.459 + * Resource Identifiers (URI): Generic Syntax</i></a>, <br><a
 151.460 + * href="http://www.ietf.org/rfc/rfc2732.txt"><i>RFC&nbsp;2732: Format for
 151.461 + * Literal IPv6 Addresses in URLs</i></a>, <br><a
 151.462 + * href="URISyntaxException.html">URISyntaxException</a>
 151.463 + */
 151.464 +
 151.465 +public final class URI
 151.466 +    implements Comparable<URI>, Serializable
 151.467 +{
 151.468 +
 151.469 +    // Note: Comments containing the word "ASSERT" indicate places where a
 151.470 +    // throw of an InternalError should be replaced by an appropriate assertion
 151.471 +    // statement once asserts are enabled in the build.
 151.472 +
 151.473 +    static final long serialVersionUID = -6052424284110960213L;
 151.474 +
 151.475 +
 151.476 +    // -- Properties and components of this instance --
 151.477 +
 151.478 +    // Components of all URIs: [<scheme>:]<scheme-specific-part>[#<fragment>]
 151.479 +    private transient String scheme;            // null ==> relative URI
 151.480 +    private transient String fragment;
 151.481 +
 151.482 +    // Hierarchical URI components: [//<authority>]<path>[?<query>]
 151.483 +    private transient String authority;         // Registry or server
 151.484 +
 151.485 +    // Server-based authority: [<userInfo>@]<host>[:<port>]
 151.486 +    private transient String userInfo;
 151.487 +    private transient String host;              // null ==> registry-based
 151.488 +    private transient int port = -1;            // -1 ==> undefined
 151.489 +
 151.490 +    // Remaining components of hierarchical URIs
 151.491 +    private transient String path;              // null ==> opaque
 151.492 +    private transient String query;
 151.493 +
 151.494 +    // The remaining fields may be computed on demand
 151.495 +
 151.496 +    private volatile transient String schemeSpecificPart;
 151.497 +    private volatile transient int hash;        // Zero ==> undefined
 151.498 +
 151.499 +    private volatile transient String decodedUserInfo = null;
 151.500 +    private volatile transient String decodedAuthority = null;
 151.501 +    private volatile transient String decodedPath = null;
 151.502 +    private volatile transient String decodedQuery = null;
 151.503 +    private volatile transient String decodedFragment = null;
 151.504 +    private volatile transient String decodedSchemeSpecificPart = null;
 151.505 +
 151.506 +    /**
 151.507 +     * The string form of this URI.
 151.508 +     *
 151.509 +     * @serial
 151.510 +     */
 151.511 +    private volatile String string;             // The only serializable field
 151.512 +
 151.513 +
 151.514 +
 151.515 +    // -- Constructors and factories --
 151.516 +
 151.517 +    private URI() { }                           // Used internally
 151.518 +
 151.519 +    /**
 151.520 +     * Constructs a URI by parsing the given string.
 151.521 +     *
 151.522 +     * <p> This constructor parses the given string exactly as specified by the
 151.523 +     * grammar in <a
 151.524 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 151.525 +     * Appendix&nbsp;A, <b><i>except for the following deviations:</i></b> </p>
 151.526 +     *
 151.527 +     * <ul type=disc>
 151.528 +     *
 151.529 +     *   <li><p> An empty authority component is permitted as long as it is
 151.530 +     *   followed by a non-empty path, a query component, or a fragment
 151.531 +     *   component.  This allows the parsing of URIs such as
 151.532 +     *   <tt>"file:///foo/bar"</tt>, which seems to be the intent of
 151.533 +     *   RFC&nbsp;2396 although the grammar does not permit it.  If the
 151.534 +     *   authority component is empty then the user-information, host, and port
 151.535 +     *   components are undefined. </p></li>
 151.536 +     *
 151.537 +     *   <li><p> Empty relative paths are permitted; this seems to be the
 151.538 +     *   intent of RFC&nbsp;2396 although the grammar does not permit it.  The
 151.539 +     *   primary consequence of this deviation is that a standalone fragment
 151.540 +     *   such as <tt>"#foo"</tt> parses as a relative URI with an empty path
 151.541 +     *   and the given fragment, and can be usefully <a
 151.542 +     *   href="#resolve-frag">resolved</a> against a base URI.
 151.543 +     *
 151.544 +     *   <li><p> IPv4 addresses in host components are parsed rigorously, as
 151.545 +     *   specified by <a
 151.546 +     *   href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>: Each
 151.547 +     *   element of a dotted-quad address must contain no more than three
 151.548 +     *   decimal digits.  Each element is further constrained to have a value
 151.549 +     *   no greater than 255. </p></li>
 151.550 +     *
 151.551 +     *   <li> <p> Hostnames in host components that comprise only a single
 151.552 +     *   domain label are permitted to start with an <i>alphanum</i>
 151.553 +     *   character. This seems to be the intent of <a
 151.554 +     *   href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>
 151.555 +     *   section&nbsp;3.2.2 although the grammar does not permit it. The
 151.556 +     *   consequence of this deviation is that the authority component of a
 151.557 +     *   hierarchical URI such as <tt>s://123</tt>, will parse as a server-based
 151.558 +     *   authority. </p></li>
 151.559 +     *
 151.560 +     *   <li><p> IPv6 addresses are permitted for the host component.  An IPv6
 151.561 +     *   address must be enclosed in square brackets (<tt>'['</tt> and
 151.562 +     *   <tt>']'</tt>) as specified by <a
 151.563 +     *   href="http://www.ietf.org/rfc/rfc2732.txt">RFC&nbsp;2732</a>.  The
 151.564 +     *   IPv6 address itself must parse according to <a
 151.565 +     *   href="http://www.ietf.org/rfc/rfc2373.txt">RFC&nbsp;2373</a>.  IPv6
 151.566 +     *   addresses are further constrained to describe no more than sixteen
 151.567 +     *   bytes of address information, a constraint implicit in RFC&nbsp;2373
 151.568 +     *   but not expressible in the grammar. </p></li>
 151.569 +     *
 151.570 +     *   <li><p> Characters in the <i>other</i> category are permitted wherever
 151.571 +     *   RFC&nbsp;2396 permits <i>escaped</i> octets, that is, in the
 151.572 +     *   user-information, path, query, and fragment components, as well as in
 151.573 +     *   the authority component if the authority is registry-based.  This
 151.574 +     *   allows URIs to contain Unicode characters beyond those in the US-ASCII
 151.575 +     *   character set. </p></li>
 151.576 +     *
 151.577 +     * </ul>
 151.578 +     *
 151.579 +     * @param  str   The string to be parsed into a URI
 151.580 +     *
 151.581 +     * @throws  NullPointerException
 151.582 +     *          If <tt>str</tt> is <tt>null</tt>
 151.583 +     *
 151.584 +     * @throws  URISyntaxException
 151.585 +     *          If the given string violates RFC&nbsp;2396, as augmented
 151.586 +     *          by the above deviations
 151.587 +     */
 151.588 +    public URI(String str) throws URISyntaxException {
 151.589 +        new Parser(str).parse(false);
 151.590 +    }
 151.591 +
 151.592 +    /**
 151.593 +     * Constructs a hierarchical URI from the given components.
 151.594 +     *
 151.595 +     * <p> If a scheme is given then the path, if also given, must either be
 151.596 +     * empty or begin with a slash character (<tt>'/'</tt>).  Otherwise a
 151.597 +     * component of the new URI may be left undefined by passing <tt>null</tt>
 151.598 +     * for the corresponding parameter or, in the case of the <tt>port</tt>
 151.599 +     * parameter, by passing <tt>-1</tt>.
 151.600 +     *
 151.601 +     * <p> This constructor first builds a URI string from the given components
 151.602 +     * according to the rules specified in <a
 151.603 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 151.604 +     * section&nbsp;5.2, step&nbsp;7: </p>
 151.605 +     *
 151.606 +     * <ol>
 151.607 +     *
 151.608 +     *   <li><p> Initially, the result string is empty. </p></li>
 151.609 +     *
 151.610 +     *   <li><p> If a scheme is given then it is appended to the result,
 151.611 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 151.612 +     *
 151.613 +     *   <li><p> If user information, a host, or a port are given then the
 151.614 +     *   string <tt>"//"</tt> is appended.  </p></li>
 151.615 +     *
 151.616 +     *   <li><p> If user information is given then it is appended, followed by
 151.617 +     *   a commercial-at character (<tt>'@'</tt>).  Any character not in the
 151.618 +     *   <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 151.619 +     *   categories is <a href="#quote">quoted</a>.  </p></li>
 151.620 +     *
 151.621 +     *   <li><p> If a host is given then it is appended.  If the host is a
 151.622 +     *   literal IPv6 address but is not enclosed in square brackets
 151.623 +     *   (<tt>'['</tt> and <tt>']'</tt>) then the square brackets are added.
 151.624 +     *   </p></li>
 151.625 +     *
 151.626 +     *   <li><p> If a port number is given then a colon character
 151.627 +     *   (<tt>':'</tt>) is appended, followed by the port number in decimal.
 151.628 +     *   </p></li>
 151.629 +     *
 151.630 +     *   <li><p> If a path is given then it is appended.  Any character not in
 151.631 +     *   the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 151.632 +     *   categories, and not equal to the slash character (<tt>'/'</tt>) or the
 151.633 +     *   commercial-at character (<tt>'@'</tt>), is quoted.  </p></li>
 151.634 +     *
 151.635 +     *   <li><p> If a query is given then a question-mark character
 151.636 +     *   (<tt>'?'</tt>) is appended, followed by the query.  Any character that
 151.637 +     *   is not a <a href="#legal-chars">legal URI character</a> is quoted.
 151.638 +     *   </p></li>
 151.639 +     *
 151.640 +     *   <li><p> Finally, if a fragment is given then a hash character
 151.641 +     *   (<tt>'#'</tt>) is appended, followed by the fragment.  Any character
 151.642 +     *   that is not a legal URI character is quoted.  </p></li>
 151.643 +     *
 151.644 +     * </ol>
 151.645 +     *
 151.646 +     * <p> The resulting URI string is then parsed as if by invoking the {@link
 151.647 +     * #URI(String)} constructor and then invoking the {@link
 151.648 +     * #parseServerAuthority()} method upon the result; this may cause a {@link
 151.649 +     * URISyntaxException} to be thrown.  </p>
 151.650 +     *
 151.651 +     * @param   scheme    Scheme name
 151.652 +     * @param   userInfo  User name and authorization information
 151.653 +     * @param   host      Host name
 151.654 +     * @param   port      Port number
 151.655 +     * @param   path      Path
 151.656 +     * @param   query     Query
 151.657 +     * @param   fragment  Fragment
 151.658 +     *
 151.659 +     * @throws URISyntaxException
 151.660 +     *         If both a scheme and a path are given but the path is relative,
 151.661 +     *         if the URI string constructed from the given components violates
 151.662 +     *         RFC&nbsp;2396, or if the authority component of the string is
 151.663 +     *         present but cannot be parsed as a server-based authority
 151.664 +     */
 151.665 +    public URI(String scheme,
 151.666 +               String userInfo, String host, int port,
 151.667 +               String path, String query, String fragment)
 151.668 +        throws URISyntaxException
 151.669 +    {
 151.670 +        String s = toString(scheme, null,
 151.671 +                            null, userInfo, host, port,
 151.672 +                            path, query, fragment);
 151.673 +        checkPath(s, scheme, path);
 151.674 +        new Parser(s).parse(true);
 151.675 +    }
 151.676 +
 151.677 +    /**
 151.678 +     * Constructs a hierarchical URI from the given components.
 151.679 +     *
 151.680 +     * <p> If a scheme is given then the path, if also given, must either be
 151.681 +     * empty or begin with a slash character (<tt>'/'</tt>).  Otherwise a
 151.682 +     * component of the new URI may be left undefined by passing <tt>null</tt>
 151.683 +     * for the corresponding parameter.
 151.684 +     *
 151.685 +     * <p> This constructor first builds a URI string from the given components
 151.686 +     * according to the rules specified in <a
 151.687 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 151.688 +     * section&nbsp;5.2, step&nbsp;7: </p>
 151.689 +     *
 151.690 +     * <ol>
 151.691 +     *
 151.692 +     *   <li><p> Initially, the result string is empty.  </p></li>
 151.693 +     *
 151.694 +     *   <li><p> If a scheme is given then it is appended to the result,
 151.695 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 151.696 +     *
 151.697 +     *   <li><p> If an authority is given then the string <tt>"//"</tt> is
 151.698 +     *   appended, followed by the authority.  If the authority contains a
 151.699 +     *   literal IPv6 address then the address must be enclosed in square
 151.700 +     *   brackets (<tt>'['</tt> and <tt>']'</tt>).  Any character not in the
 151.701 +     *   <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 151.702 +     *   categories, and not equal to the commercial-at character
 151.703 +     *   (<tt>'@'</tt>), is <a href="#quote">quoted</a>.  </p></li>
 151.704 +     *
 151.705 +     *   <li><p> If a path is given then it is appended.  Any character not in
 151.706 +     *   the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, or <i>other</i>
 151.707 +     *   categories, and not equal to the slash character (<tt>'/'</tt>) or the
 151.708 +     *   commercial-at character (<tt>'@'</tt>), is quoted.  </p></li>
 151.709 +     *
 151.710 +     *   <li><p> If a query is given then a question-mark character
 151.711 +     *   (<tt>'?'</tt>) is appended, followed by the query.  Any character that
 151.712 +     *   is not a <a href="#legal-chars">legal URI character</a> is quoted.
 151.713 +     *   </p></li>
 151.714 +     *
 151.715 +     *   <li><p> Finally, if a fragment is given then a hash character
 151.716 +     *   (<tt>'#'</tt>) is appended, followed by the fragment.  Any character
 151.717 +     *   that is not a legal URI character is quoted.  </p></li>
 151.718 +     *
 151.719 +     * </ol>
 151.720 +     *
 151.721 +     * <p> The resulting URI string is then parsed as if by invoking the {@link
 151.722 +     * #URI(String)} constructor and then invoking the {@link
 151.723 +     * #parseServerAuthority()} method upon the result; this may cause a {@link
 151.724 +     * URISyntaxException} to be thrown.  </p>
 151.725 +     *
 151.726 +     * @param   scheme     Scheme name
 151.727 +     * @param   authority  Authority
 151.728 +     * @param   path       Path
 151.729 +     * @param   query      Query
 151.730 +     * @param   fragment   Fragment
 151.731 +     *
 151.732 +     * @throws URISyntaxException
 151.733 +     *         If both a scheme and a path are given but the path is relative,
 151.734 +     *         if the URI string constructed from the given components violates
 151.735 +     *         RFC&nbsp;2396, or if the authority component of the string is
 151.736 +     *         present but cannot be parsed as a server-based authority
 151.737 +     */
 151.738 +    public URI(String scheme,
 151.739 +               String authority,
 151.740 +               String path, String query, String fragment)
 151.741 +        throws URISyntaxException
 151.742 +    {
 151.743 +        String s = toString(scheme, null,
 151.744 +                            authority, null, null, -1,
 151.745 +                            path, query, fragment);
 151.746 +        checkPath(s, scheme, path);
 151.747 +        new Parser(s).parse(false);
 151.748 +    }
 151.749 +
 151.750 +    /**
 151.751 +     * Constructs a hierarchical URI from the given components.
 151.752 +     *
 151.753 +     * <p> A component may be left undefined by passing <tt>null</tt>.
 151.754 +     *
 151.755 +     * <p> This convenience constructor works as if by invoking the
 151.756 +     * seven-argument constructor as follows:
 151.757 +     *
 151.758 +     * <blockquote><tt>
 151.759 +     * new&nbsp;{@link #URI(String, String, String, int, String, String, String)
 151.760 +     * URI}(scheme,&nbsp;null,&nbsp;host,&nbsp;-1,&nbsp;path,&nbsp;null,&nbsp;fragment);
 151.761 +     * </tt></blockquote>
 151.762 +     *
 151.763 +     * @param   scheme    Scheme name
 151.764 +     * @param   host      Host name
 151.765 +     * @param   path      Path
 151.766 +     * @param   fragment  Fragment
 151.767 +     *
 151.768 +     * @throws  URISyntaxException
 151.769 +     *          If the URI string constructed from the given components
 151.770 +     *          violates RFC&nbsp;2396
 151.771 +     */
 151.772 +    public URI(String scheme, String host, String path, String fragment)
 151.773 +        throws URISyntaxException
 151.774 +    {
 151.775 +        this(scheme, null, host, -1, path, null, fragment);
 151.776 +    }
 151.777 +
 151.778 +    /**
 151.779 +     * Constructs a URI from the given components.
 151.780 +     *
 151.781 +     * <p> A component may be left undefined by passing <tt>null</tt>.
 151.782 +     *
 151.783 +     * <p> This constructor first builds a URI in string form using the given
 151.784 +     * components as follows:  </p>
 151.785 +     *
 151.786 +     * <ol>
 151.787 +     *
 151.788 +     *   <li><p> Initially, the result string is empty.  </p></li>
 151.789 +     *
 151.790 +     *   <li><p> If a scheme is given then it is appended to the result,
 151.791 +     *   followed by a colon character (<tt>':'</tt>).  </p></li>
 151.792 +     *
 151.793 +     *   <li><p> If a scheme-specific part is given then it is appended.  Any
 151.794 +     *   character that is not a <a href="#legal-chars">legal URI character</a>
 151.795 +     *   is <a href="#quote">quoted</a>.  </p></li>
 151.796 +     *
 151.797 +     *   <li><p> Finally, if a fragment is given then a hash character
 151.798 +     *   (<tt>'#'</tt>) is appended to the string, followed by the fragment.
 151.799 +     *   Any character that is not a legal URI character is quoted.  </p></li>
 151.800 +     *
 151.801 +     * </ol>
 151.802 +     *
 151.803 +     * <p> The resulting URI string is then parsed in order to create the new
 151.804 +     * URI instance as if by invoking the {@link #URI(String)} constructor;
 151.805 +     * this may cause a {@link URISyntaxException} to be thrown.  </p>
 151.806 +     *
 151.807 +     * @param   scheme    Scheme name
 151.808 +     * @param   ssp       Scheme-specific part
 151.809 +     * @param   fragment  Fragment
 151.810 +     *
 151.811 +     * @throws  URISyntaxException
 151.812 +     *          If the URI string constructed from the given components
 151.813 +     *          violates RFC&nbsp;2396
 151.814 +     */
 151.815 +    public URI(String scheme, String ssp, String fragment)
 151.816 +        throws URISyntaxException
 151.817 +    {
 151.818 +        new Parser(toString(scheme, ssp,
 151.819 +                            null, null, null, -1,
 151.820 +                            null, null, fragment))
 151.821 +            .parse(false);
 151.822 +    }
 151.823 +
 151.824 +    /**
 151.825 +     * Creates a URI by parsing the given string.
 151.826 +     *
 151.827 +     * <p> This convenience factory method works as if by invoking the {@link
 151.828 +     * #URI(String)} constructor; any {@link URISyntaxException} thrown by the
 151.829 +     * constructor is caught and wrapped in a new {@link
 151.830 +     * IllegalArgumentException} object, which is then thrown.
 151.831 +     *
 151.832 +     * <p> This method is provided for use in situations where it is known that
 151.833 +     * the given string is a legal URI, for example for URI constants declared
 151.834 +     * within in a program, and so it would be considered a programming error
 151.835 +     * for the string not to parse as such.  The constructors, which throw
 151.836 +     * {@link URISyntaxException} directly, should be used situations where a
 151.837 +     * URI is being constructed from user input or from some other source that
 151.838 +     * may be prone to errors.  </p>
 151.839 +     *
 151.840 +     * @param  str   The string to be parsed into a URI
 151.841 +     * @return The new URI
 151.842 +     *
 151.843 +     * @throws  NullPointerException
 151.844 +     *          If <tt>str</tt> is <tt>null</tt>
 151.845 +     *
 151.846 +     * @throws  IllegalArgumentException
 151.847 +     *          If the given string violates RFC&nbsp;2396
 151.848 +     */
 151.849 +    public static URI create(String str) {
 151.850 +        try {
 151.851 +            return new URI(str);
 151.852 +        } catch (URISyntaxException x) {
 151.853 +            throw new IllegalArgumentException(x.getMessage(), x);
 151.854 +        }
 151.855 +    }
 151.856 +
 151.857 +
 151.858 +    // -- Operations --
 151.859 +
 151.860 +    /**
 151.861 +     * Attempts to parse this URI's authority component, if defined, into
 151.862 +     * user-information, host, and port components.
 151.863 +     *
 151.864 +     * <p> If this URI's authority component has already been recognized as
 151.865 +     * being server-based then it will already have been parsed into
 151.866 +     * user-information, host, and port components.  In this case, or if this
 151.867 +     * URI has no authority component, this method simply returns this URI.
 151.868 +     *
 151.869 +     * <p> Otherwise this method attempts once more to parse the authority
 151.870 +     * component into user-information, host, and port components, and throws
 151.871 +     * an exception describing why the authority component could not be parsed
 151.872 +     * in that way.
 151.873 +     *
 151.874 +     * <p> This method is provided because the generic URI syntax specified in
 151.875 +     * <a href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>
 151.876 +     * cannot always distinguish a malformed server-based authority from a
 151.877 +     * legitimate registry-based authority.  It must therefore treat some
 151.878 +     * instances of the former as instances of the latter.  The authority
 151.879 +     * component in the URI string <tt>"//foo:bar"</tt>, for example, is not a
 151.880 +     * legal server-based authority but it is legal as a registry-based
 151.881 +     * authority.
 151.882 +     *
 151.883 +     * <p> In many common situations, for example when working URIs that are
 151.884 +     * known to be either URNs or URLs, the hierarchical URIs being used will
 151.885 +     * always be server-based.  They therefore must either be parsed as such or
 151.886 +     * treated as an error.  In these cases a statement such as
 151.887 +     *
 151.888 +     * <blockquote>
 151.889 +     * <tt>URI </tt><i>u</i><tt> = new URI(str).parseServerAuthority();</tt>
 151.890 +     * </blockquote>
 151.891 +     *
 151.892 +     * <p> can be used to ensure that <i>u</i> always refers to a URI that, if
 151.893 +     * it has an authority component, has a server-based authority with proper
 151.894 +     * user-information, host, and port components.  Invoking this method also
 151.895 +     * ensures that if the authority could not be parsed in that way then an
 151.896 +     * appropriate diagnostic message can be issued based upon the exception
 151.897 +     * that is thrown. </p>
 151.898 +     *
 151.899 +     * @return  A URI whose authority field has been parsed
 151.900 +     *          as a server-based authority
 151.901 +     *
 151.902 +     * @throws  URISyntaxException
 151.903 +     *          If the authority component of this URI is defined
 151.904 +     *          but cannot be parsed as a server-based authority
 151.905 +     *          according to RFC&nbsp;2396
 151.906 +     */
 151.907 +    public URI parseServerAuthority()
 151.908 +        throws URISyntaxException
 151.909 +    {
 151.910 +        // We could be clever and cache the error message and index from the
 151.911 +        // exception thrown during the original parse, but that would require
 151.912 +        // either more fields or a more-obscure representation.
 151.913 +        if ((host != null) || (authority == null))
 151.914 +            return this;
 151.915 +        defineString();
 151.916 +        new Parser(string).parse(true);
 151.917 +        return this;
 151.918 +    }
 151.919 +
 151.920 +    /**
 151.921 +     * Normalizes this URI's path.
 151.922 +     *
 151.923 +     * <p> If this URI is opaque, or if its path is already in normal form,
 151.924 +     * then this URI is returned.  Otherwise a new URI is constructed that is
 151.925 +     * identical to this URI except that its path is computed by normalizing
 151.926 +     * this URI's path in a manner consistent with <a
 151.927 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 151.928 +     * section&nbsp;5.2, step&nbsp;6, sub-steps&nbsp;c through&nbsp;f; that is:
 151.929 +     * </p>
 151.930 +     *
 151.931 +     * <ol>
 151.932 +     *
 151.933 +     *   <li><p> All <tt>"."</tt> segments are removed. </p></li>
 151.934 +     *
 151.935 +     *   <li><p> If a <tt>".."</tt> segment is preceded by a non-<tt>".."</tt>
 151.936 +     *   segment then both of these segments are removed.  This step is
 151.937 +     *   repeated until it is no longer applicable. </p></li>
 151.938 +     *
 151.939 +     *   <li><p> If the path is relative, and if its first segment contains a
 151.940 +     *   colon character (<tt>':'</tt>), then a <tt>"."</tt> segment is
 151.941 +     *   prepended.  This prevents a relative URI with a path such as
 151.942 +     *   <tt>"a:b/c/d"</tt> from later being re-parsed as an opaque URI with a
 151.943 +     *   scheme of <tt>"a"</tt> and a scheme-specific part of <tt>"b/c/d"</tt>.
 151.944 +     *   <b><i>(Deviation from RFC&nbsp;2396)</i></b> </p></li>
 151.945 +     *
 151.946 +     * </ol>
 151.947 +     *
 151.948 +     * <p> A normalized path will begin with one or more <tt>".."</tt> segments
 151.949 +     * if there were insufficient non-<tt>".."</tt> segments preceding them to
 151.950 +     * allow their removal.  A normalized path will begin with a <tt>"."</tt>
 151.951 +     * segment if one was inserted by step 3 above.  Otherwise, a normalized
 151.952 +     * path will not contain any <tt>"."</tt> or <tt>".."</tt> segments. </p>
 151.953 +     *
 151.954 +     * @return  A URI equivalent to this URI,
 151.955 +     *          but whose path is in normal form
 151.956 +     */
 151.957 +    public URI normalize() {
 151.958 +        return normalize(this);
 151.959 +    }
 151.960 +
 151.961 +    /**
 151.962 +     * Resolves the given URI against this URI.
 151.963 +     *
 151.964 +     * <p> If the given URI is already absolute, or if this URI is opaque, then
 151.965 +     * the given URI is returned.
 151.966 +     *
 151.967 +     * <p><a name="resolve-frag"></a> If the given URI's fragment component is
 151.968 +     * defined, its path component is empty, and its scheme, authority, and
 151.969 +     * query components are undefined, then a URI with the given fragment but
 151.970 +     * with all other components equal to those of this URI is returned.  This
 151.971 +     * allows a URI representing a standalone fragment reference, such as
 151.972 +     * <tt>"#foo"</tt>, to be usefully resolved against a base URI.
 151.973 +     *
 151.974 +     * <p> Otherwise this method constructs a new hierarchical URI in a manner
 151.975 +     * consistent with <a
 151.976 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
 151.977 +     * section&nbsp;5.2; that is: </p>
 151.978 +     *
 151.979 +     * <ol>
 151.980 +     *
 151.981 +     *   <li><p> A new URI is constructed with this URI's scheme and the given
 151.982 +     *   URI's query and fragment components. </p></li>
 151.983 +     *
 151.984 +     *   <li><p> If the given URI has an authority component then the new URI's
 151.985 +     *   authority and path are taken from the given URI. </p></li>
 151.986 +     *
 151.987 +     *   <li><p> Otherwise the new URI's authority component is copied from
 151.988 +     *   this URI, and its path is computed as follows: </p>
 151.989 +     *
 151.990 +     *   <ol type=a>
 151.991 +     *
 151.992 +     *     <li><p> If the given URI's path is absolute then the new URI's path
 151.993 +     *     is taken from the given URI. </p></li>
 151.994 +     *
 151.995 +     *     <li><p> Otherwise the given URI's path is relative, and so the new
 151.996 +     *     URI's path is computed by resolving the path of the given URI
 151.997 +     *     against the path of this URI.  This is done by concatenating all but
 151.998 +     *     the last segment of this URI's path, if any, with the given URI's
 151.999 +     *     path and then normalizing the result as if by invoking the {@link
151.1000 +     *     #normalize() normalize} method. </p></li>
151.1001 +     *
151.1002 +     *   </ol></li>
151.1003 +     *
151.1004 +     * </ol>
151.1005 +     *
151.1006 +     * <p> The result of this method is absolute if, and only if, either this
151.1007 +     * URI is absolute or the given URI is absolute.  </p>
151.1008 +     *
151.1009 +     * @param  uri  The URI to be resolved against this URI
151.1010 +     * @return The resulting URI
151.1011 +     *
151.1012 +     * @throws  NullPointerException
151.1013 +     *          If <tt>uri</tt> is <tt>null</tt>
151.1014 +     */
151.1015 +    public URI resolve(URI uri) {
151.1016 +        return resolve(this, uri);
151.1017 +    }
151.1018 +
151.1019 +    /**
151.1020 +     * Constructs a new URI by parsing the given string and then resolving it
151.1021 +     * against this URI.
151.1022 +     *
151.1023 +     * <p> This convenience method works as if invoking it were equivalent to
151.1024 +     * evaluating the expression <tt>{@link #resolve(java.net.URI)
151.1025 +     * resolve}(URI.{@link #create(String) create}(str))</tt>. </p>
151.1026 +     *
151.1027 +     * @param  str   The string to be parsed into a URI
151.1028 +     * @return The resulting URI
151.1029 +     *
151.1030 +     * @throws  NullPointerException
151.1031 +     *          If <tt>str</tt> is <tt>null</tt>
151.1032 +     *
151.1033 +     * @throws  IllegalArgumentException
151.1034 +     *          If the given string violates RFC&nbsp;2396
151.1035 +     */
151.1036 +    public URI resolve(String str) {
151.1037 +        return resolve(URI.create(str));
151.1038 +    }
151.1039 +
151.1040 +    /**
151.1041 +     * Relativizes the given URI against this URI.
151.1042 +     *
151.1043 +     * <p> The relativization of the given URI against this URI is computed as
151.1044 +     * follows: </p>
151.1045 +     *
151.1046 +     * <ol>
151.1047 +     *
151.1048 +     *   <li><p> If either this URI or the given URI are opaque, or if the
151.1049 +     *   scheme and authority components of the two URIs are not identical, or
151.1050 +     *   if the path of this URI is not a prefix of the path of the given URI,
151.1051 +     *   then the given URI is returned. </p></li>
151.1052 +     *
151.1053 +     *   <li><p> Otherwise a new relative hierarchical URI is constructed with
151.1054 +     *   query and fragment components taken from the given URI and with a path
151.1055 +     *   component computed by removing this URI's path from the beginning of
151.1056 +     *   the given URI's path. </p></li>
151.1057 +     *
151.1058 +     * </ol>
151.1059 +     *
151.1060 +     * @param  uri  The URI to be relativized against this URI
151.1061 +     * @return The resulting URI
151.1062 +     *
151.1063 +     * @throws  NullPointerException
151.1064 +     *          If <tt>uri</tt> is <tt>null</tt>
151.1065 +     */
151.1066 +    public URI relativize(URI uri) {
151.1067 +        return relativize(this, uri);
151.1068 +    }
151.1069 +
151.1070 +    /**
151.1071 +     * Constructs a URL from this URI.
151.1072 +     *
151.1073 +     * <p> This convenience method works as if invoking it were equivalent to
151.1074 +     * evaluating the expression <tt>new&nbsp;URL(this.toString())</tt> after
151.1075 +     * first checking that this URI is absolute. </p>
151.1076 +     *
151.1077 +     * @return  A URL constructed from this URI
151.1078 +     *
151.1079 +     * @throws  IllegalArgumentException
151.1080 +     *          If this URL is not absolute
151.1081 +     *
151.1082 +     * @throws  MalformedURLException
151.1083 +     *          If a protocol handler for the URL could not be found,
151.1084 +     *          or if some other error occurred while constructing the URL
151.1085 +     */
151.1086 +    public URL toURL()
151.1087 +        throws MalformedURLException {
151.1088 +        if (!isAbsolute())
151.1089 +            throw new IllegalArgumentException("URI is not absolute");
151.1090 +        return new URL(toString());
151.1091 +    }
151.1092 +
151.1093 +    // -- Component access methods --
151.1094 +
151.1095 +    /**
151.1096 +     * Returns the scheme component of this URI.
151.1097 +     *
151.1098 +     * <p> The scheme component of a URI, if defined, only contains characters
151.1099 +     * in the <i>alphanum</i> category and in the string <tt>"-.+"</tt>.  A
151.1100 +     * scheme always starts with an <i>alpha</i> character. <p>
151.1101 +     *
151.1102 +     * The scheme component of a URI cannot contain escaped octets, hence this
151.1103 +     * method does not perform any decoding.
151.1104 +     *
151.1105 +     * @return  The scheme component of this URI,
151.1106 +     *          or <tt>null</tt> if the scheme is undefined
151.1107 +     */
151.1108 +    public String getScheme() {
151.1109 +        return scheme;
151.1110 +    }
151.1111 +
151.1112 +    /**
151.1113 +     * Tells whether or not this URI is absolute.
151.1114 +     *
151.1115 +     * <p> A URI is absolute if, and only if, it has a scheme component. </p>
151.1116 +     *
151.1117 +     * @return  <tt>true</tt> if, and only if, this URI is absolute
151.1118 +     */
151.1119 +    public boolean isAbsolute() {
151.1120 +        return scheme != null;
151.1121 +    }
151.1122 +
151.1123 +    /**
151.1124 +     * Tells whether or not this URI is opaque.
151.1125 +     *
151.1126 +     * <p> A URI is opaque if, and only if, it is absolute and its
151.1127 +     * scheme-specific part does not begin with a slash character ('/').
151.1128 +     * An opaque URI has a scheme, a scheme-specific part, and possibly
151.1129 +     * a fragment; all other components are undefined. </p>
151.1130 +     *
151.1131 +     * @return  <tt>true</tt> if, and only if, this URI is opaque
151.1132 +     */
151.1133 +    public boolean isOpaque() {
151.1134 +        return path == null;
151.1135 +    }
151.1136 +
151.1137 +    /**
151.1138 +     * Returns the raw scheme-specific part of this URI.  The scheme-specific
151.1139 +     * part is never undefined, though it may be empty.
151.1140 +     *
151.1141 +     * <p> The scheme-specific part of a URI only contains legal URI
151.1142 +     * characters. </p>
151.1143 +     *
151.1144 +     * @return  The raw scheme-specific part of this URI
151.1145 +     *          (never <tt>null</tt>)
151.1146 +     */
151.1147 +    public String getRawSchemeSpecificPart() {
151.1148 +        defineSchemeSpecificPart();
151.1149 +        return schemeSpecificPart;
151.1150 +    }
151.1151 +
151.1152 +    /**
151.1153 +     * Returns the decoded scheme-specific part of this URI.
151.1154 +     *
151.1155 +     * <p> The string returned by this method is equal to that returned by the
151.1156 +     * {@link #getRawSchemeSpecificPart() getRawSchemeSpecificPart} method
151.1157 +     * except that all sequences of escaped octets are <a
151.1158 +     * href="#decode">decoded</a>.  </p>
151.1159 +     *
151.1160 +     * @return  The decoded scheme-specific part of this URI
151.1161 +     *          (never <tt>null</tt>)
151.1162 +     */
151.1163 +    public String getSchemeSpecificPart() {
151.1164 +        if (decodedSchemeSpecificPart == null)
151.1165 +            decodedSchemeSpecificPart = decode(getRawSchemeSpecificPart());
151.1166 +        return decodedSchemeSpecificPart;
151.1167 +    }
151.1168 +
151.1169 +    /**
151.1170 +     * Returns the raw authority component of this URI.
151.1171 +     *
151.1172 +     * <p> The authority component of a URI, if defined, only contains the
151.1173 +     * commercial-at character (<tt>'@'</tt>) and characters in the
151.1174 +     * <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, and <i>other</i>
151.1175 +     * categories.  If the authority is server-based then it is further
151.1176 +     * constrained to have valid user-information, host, and port
151.1177 +     * components. </p>
151.1178 +     *
151.1179 +     * @return  The raw authority component of this URI,
151.1180 +     *          or <tt>null</tt> if the authority is undefined
151.1181 +     */
151.1182 +    public String getRawAuthority() {
151.1183 +        return authority;
151.1184 +    }
151.1185 +
151.1186 +    /**
151.1187 +     * Returns the decoded authority component of this URI.
151.1188 +     *
151.1189 +     * <p> The string returned by this method is equal to that returned by the
151.1190 +     * {@link #getRawAuthority() getRawAuthority} method except that all
151.1191 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
151.1192 +     *
151.1193 +     * @return  The decoded authority component of this URI,
151.1194 +     *          or <tt>null</tt> if the authority is undefined
151.1195 +     */
151.1196 +    public String getAuthority() {
151.1197 +        if (decodedAuthority == null)
151.1198 +            decodedAuthority = decode(authority);
151.1199 +        return decodedAuthority;
151.1200 +    }
151.1201 +
151.1202 +    /**
151.1203 +     * Returns the raw user-information component of this URI.
151.1204 +     *
151.1205 +     * <p> The user-information component of a URI, if defined, only contains
151.1206 +     * characters in the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>, and
151.1207 +     * <i>other</i> categories. </p>
151.1208 +     *
151.1209 +     * @return  The raw user-information component of this URI,
151.1210 +     *          or <tt>null</tt> if the user information is undefined
151.1211 +     */
151.1212 +    public String getRawUserInfo() {
151.1213 +        return userInfo;
151.1214 +    }
151.1215 +
151.1216 +    /**
151.1217 +     * Returns the decoded user-information component of this URI.
151.1218 +     *
151.1219 +     * <p> The string returned by this method is equal to that returned by the
151.1220 +     * {@link #getRawUserInfo() getRawUserInfo} method except that all
151.1221 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
151.1222 +     *
151.1223 +     * @return  The decoded user-information component of this URI,
151.1224 +     *          or <tt>null</tt> if the user information is undefined
151.1225 +     */
151.1226 +    public String getUserInfo() {
151.1227 +        if ((decodedUserInfo == null) && (userInfo != null))
151.1228 +            decodedUserInfo = decode(userInfo);
151.1229 +        return decodedUserInfo;
151.1230 +    }
151.1231 +
151.1232 +    /**
151.1233 +     * Returns the host component of this URI.
151.1234 +     *
151.1235 +     * <p> The host component of a URI, if defined, will have one of the
151.1236 +     * following forms: </p>
151.1237 +     *
151.1238 +     * <ul type=disc>
151.1239 +     *
151.1240 +     *   <li><p> A domain name consisting of one or more <i>labels</i>
151.1241 +     *   separated by period characters (<tt>'.'</tt>), optionally followed by
151.1242 +     *   a period character.  Each label consists of <i>alphanum</i> characters
151.1243 +     *   as well as hyphen characters (<tt>'-'</tt>), though hyphens never
151.1244 +     *   occur as the first or last characters in a label. The rightmost
151.1245 +     *   label of a domain name consisting of two or more labels, begins
151.1246 +     *   with an <i>alpha</i> character. </li>
151.1247 +     *
151.1248 +     *   <li><p> A dotted-quad IPv4 address of the form
151.1249 +     *   <i>digit</i><tt>+.</tt><i>digit</i><tt>+.</tt><i>digit</i><tt>+.</tt><i>digit</i><tt>+</tt>,
151.1250 +     *   where no <i>digit</i> sequence is longer than three characters and no
151.1251 +     *   sequence has a value larger than 255. </p></li>
151.1252 +     *
151.1253 +     *   <li><p> An IPv6 address enclosed in square brackets (<tt>'['</tt> and
151.1254 +     *   <tt>']'</tt>) and consisting of hexadecimal digits, colon characters
151.1255 +     *   (<tt>':'</tt>), and possibly an embedded IPv4 address.  The full
151.1256 +     *   syntax of IPv6 addresses is specified in <a
151.1257 +     *   href="http://www.ietf.org/rfc/rfc2373.txt"><i>RFC&nbsp;2373: IPv6
151.1258 +     *   Addressing Architecture</i></a>.  </p></li>
151.1259 +     *
151.1260 +     * </ul>
151.1261 +     *
151.1262 +     * The host component of a URI cannot contain escaped octets, hence this
151.1263 +     * method does not perform any decoding.
151.1264 +     *
151.1265 +     * @return  The host component of this URI,
151.1266 +     *          or <tt>null</tt> if the host is undefined
151.1267 +     */
151.1268 +    public String getHost() {
151.1269 +        return host;
151.1270 +    }
151.1271 +
151.1272 +    /**
151.1273 +     * Returns the port number of this URI.
151.1274 +     *
151.1275 +     * <p> The port component of a URI, if defined, is a non-negative
151.1276 +     * integer. </p>
151.1277 +     *
151.1278 +     * @return  The port component of this URI,
151.1279 +     *          or <tt>-1</tt> if the port is undefined
151.1280 +     */
151.1281 +    public int getPort() {
151.1282 +        return port;
151.1283 +    }
151.1284 +
151.1285 +    /**
151.1286 +     * Returns the raw path component of this URI.
151.1287 +     *
151.1288 +     * <p> The path component of a URI, if defined, only contains the slash
151.1289 +     * character (<tt>'/'</tt>), the commercial-at character (<tt>'@'</tt>),
151.1290 +     * and characters in the <i>unreserved</i>, <i>punct</i>, <i>escaped</i>,
151.1291 +     * and <i>other</i> categories. </p>
151.1292 +     *
151.1293 +     * @return  The path component of this URI,
151.1294 +     *          or <tt>null</tt> if the path is undefined
151.1295 +     */
151.1296 +    public String getRawPath() {
151.1297 +        return path;
151.1298 +    }
151.1299 +
151.1300 +    /**
151.1301 +     * Returns the decoded path component of this URI.
151.1302 +     *
151.1303 +     * <p> The string returned by this method is equal to that returned by the
151.1304 +     * {@link #getRawPath() getRawPath} method except that all sequences of
151.1305 +     * escaped octets are <a href="#decode">decoded</a>.  </p>
151.1306 +     *
151.1307 +     * @return  The decoded path component of this URI,
151.1308 +     *          or <tt>null</tt> if the path is undefined
151.1309 +     */
151.1310 +    public String getPath() {
151.1311 +        if ((decodedPath == null) && (path != null))
151.1312 +            decodedPath = decode(path);
151.1313 +        return decodedPath;
151.1314 +    }
151.1315 +
151.1316 +    /**
151.1317 +     * Returns the raw query component of this URI.
151.1318 +     *
151.1319 +     * <p> The query component of a URI, if defined, only contains legal URI
151.1320 +     * characters. </p>
151.1321 +     *
151.1322 +     * @return  The raw query component of this URI,
151.1323 +     *          or <tt>null</tt> if the query is undefined
151.1324 +     */
151.1325 +    public String getRawQuery() {
151.1326 +        return query;
151.1327 +    }
151.1328 +
151.1329 +    /**
151.1330 +     * Returns the decoded query component of this URI.
151.1331 +     *
151.1332 +     * <p> The string returned by this method is equal to that returned by the
151.1333 +     * {@link #getRawQuery() getRawQuery} method except that all sequences of
151.1334 +     * escaped octets are <a href="#decode">decoded</a>.  </p>
151.1335 +     *
151.1336 +     * @return  The decoded query component of this URI,
151.1337 +     *          or <tt>null</tt> if the query is undefined
151.1338 +     */
151.1339 +    public String getQuery() {
151.1340 +        if ((decodedQuery == null) && (query != null))
151.1341 +            decodedQuery = decode(query);
151.1342 +        return decodedQuery;
151.1343 +    }
151.1344 +
151.1345 +    /**
151.1346 +     * Returns the raw fragment component of this URI.
151.1347 +     *
151.1348 +     * <p> The fragment component of a URI, if defined, only contains legal URI
151.1349 +     * characters. </p>
151.1350 +     *
151.1351 +     * @return  The raw fragment component of this URI,
151.1352 +     *          or <tt>null</tt> if the fragment is undefined
151.1353 +     */
151.1354 +    public String getRawFragment() {
151.1355 +        return fragment;
151.1356 +    }
151.1357 +
151.1358 +    /**
151.1359 +     * Returns the decoded fragment component of this URI.
151.1360 +     *
151.1361 +     * <p> The string returned by this method is equal to that returned by the
151.1362 +     * {@link #getRawFragment() getRawFragment} method except that all
151.1363 +     * sequences of escaped octets are <a href="#decode">decoded</a>.  </p>
151.1364 +     *
151.1365 +     * @return  The decoded fragment component of this URI,
151.1366 +     *          or <tt>null</tt> if the fragment is undefined
151.1367 +     */
151.1368 +    public String getFragment() {
151.1369 +        if ((decodedFragment == null) && (fragment != null))
151.1370 +            decodedFragment = decode(fragment);
151.1371 +        return decodedFragment;
151.1372 +    }
151.1373 +
151.1374 +
151.1375 +    // -- Equality, comparison, hash code, toString, and serialization --
151.1376 +
151.1377 +    /**
151.1378 +     * Tests this URI for equality with another object.
151.1379 +     *
151.1380 +     * <p> If the given object is not a URI then this method immediately
151.1381 +     * returns <tt>false</tt>.
151.1382 +     *
151.1383 +     * <p> For two URIs to be considered equal requires that either both are
151.1384 +     * opaque or both are hierarchical.  Their schemes must either both be
151.1385 +     * undefined or else be equal without regard to case. Their fragments
151.1386 +     * must either both be undefined or else be equal.
151.1387 +     *
151.1388 +     * <p> For two opaque URIs to be considered equal, their scheme-specific
151.1389 +     * parts must be equal.
151.1390 +     *
151.1391 +     * <p> For two hierarchical URIs to be considered equal, their paths must
151.1392 +     * be equal and their queries must either both be undefined or else be
151.1393 +     * equal.  Their authorities must either both be undefined, or both be
151.1394 +     * registry-based, or both be server-based.  If their authorities are
151.1395 +     * defined and are registry-based, then they must be equal.  If their
151.1396 +     * authorities are defined and are server-based, then their hosts must be
151.1397 +     * equal without regard to case, their port numbers must be equal, and
151.1398 +     * their user-information components must be equal.
151.1399 +     *
151.1400 +     * <p> When testing the user-information, path, query, fragment, authority,
151.1401 +     * or scheme-specific parts of two URIs for equality, the raw forms rather
151.1402 +     * than the encoded forms of these components are compared and the
151.1403 +     * hexadecimal digits of escaped octets are compared without regard to
151.1404 +     * case.
151.1405 +     *
151.1406 +     * <p> This method satisfies the general contract of the {@link
151.1407 +     * java.lang.Object#equals(Object) Object.equals} method. </p>
151.1408 +     *
151.1409 +     * @param   ob   The object to which this object is to be compared
151.1410 +     *
151.1411 +     * @return  <tt>true</tt> if, and only if, the given object is a URI that
151.1412 +     *          is identical to this URI
151.1413 +     */
151.1414 +    public boolean equals(Object ob) {
151.1415 +        if (ob == this)
151.1416 +            return true;
151.1417 +        if (!(ob instanceof URI))
151.1418 +            return false;
151.1419 +        URI that = (URI)ob;
151.1420 +        if (this.isOpaque() != that.isOpaque()) return false;
151.1421 +        if (!equalIgnoringCase(this.scheme, that.scheme)) return false;
151.1422 +        if (!equal(this.fragment, that.fragment)) return false;
151.1423 +
151.1424 +        // Opaque
151.1425 +        if (this.isOpaque())
151.1426 +            return equal(this.schemeSpecificPart, that.schemeSpecificPart);
151.1427 +
151.1428 +        // Hierarchical
151.1429 +        if (!equal(this.path, that.path)) return false;
151.1430 +        if (!equal(this.query, that.query)) return false;
151.1431 +
151.1432 +        // Authorities
151.1433 +        if (this.authority == that.authority) return true;
151.1434 +        if (this.host != null) {
151.1435 +            // Server-based
151.1436 +            if (!equal(this.userInfo, that.userInfo)) return false;
151.1437 +            if (!equalIgnoringCase(this.host, that.host)) return false;
151.1438 +            if (this.port != that.port) return false;
151.1439 +        } else if (this.authority != null) {
151.1440 +            // Registry-based
151.1441 +            if (!equal(this.authority, that.authority)) return false;
151.1442 +        } else if (this.authority != that.authority) {
151.1443 +            return false;
151.1444 +        }
151.1445 +
151.1446 +        return true;
151.1447 +    }
151.1448 +
151.1449 +    /**
151.1450 +     * Returns a hash-code value for this URI.  The hash code is based upon all
151.1451 +     * of the URI's components, and satisfies the general contract of the
151.1452 +     * {@link java.lang.Object#hashCode() Object.hashCode} method.
151.1453 +     *
151.1454 +     * @return  A hash-code value for this URI
151.1455 +     */
151.1456 +    public int hashCode() {
151.1457 +        if (hash != 0)
151.1458 +            return hash;
151.1459 +        int h = hashIgnoringCase(0, scheme);
151.1460 +        h = hash(h, fragment);
151.1461 +        if (isOpaque()) {
151.1462 +            h = hash(h, schemeSpecificPart);
151.1463 +        } else {
151.1464 +            h = hash(h, path);
151.1465 +            h = hash(h, query);
151.1466 +            if (host != null) {
151.1467 +                h = hash(h, userInfo);
151.1468 +                h = hashIgnoringCase(h, host);
151.1469 +                h += 1949 * port;
151.1470 +            } else {
151.1471 +                h = hash(h, authority);
151.1472 +            }
151.1473 +        }
151.1474 +        hash = h;
151.1475 +        return h;
151.1476 +    }
151.1477 +
151.1478 +    /**
151.1479 +     * Compares this URI to another object, which must be a URI.
151.1480 +     *
151.1481 +     * <p> When comparing corresponding components of two URIs, if one
151.1482 +     * component is undefined but the other is defined then the first is
151.1483 +     * considered to be less than the second.  Unless otherwise noted, string
151.1484 +     * components are ordered according to their natural, case-sensitive
151.1485 +     * ordering as defined by the {@link java.lang.String#compareTo(Object)
151.1486 +     * String.compareTo} method.  String components that are subject to
151.1487 +     * encoding are compared by comparing their raw forms rather than their
151.1488 +     * encoded forms.
151.1489 +     *
151.1490 +     * <p> The ordering of URIs is defined as follows: </p>
151.1491 +     *
151.1492 +     * <ul type=disc>
151.1493 +     *
151.1494 +     *   <li><p> Two URIs with different schemes are ordered according the
151.1495 +     *   ordering of their schemes, without regard to case. </p></li>
151.1496 +     *
151.1497 +     *   <li><p> A hierarchical URI is considered to be less than an opaque URI
151.1498 +     *   with an identical scheme. </p></li>
151.1499 +     *
151.1500 +     *   <li><p> Two opaque URIs with identical schemes are ordered according
151.1501 +     *   to the ordering of their scheme-specific parts. </p></li>
151.1502 +     *
151.1503 +     *   <li><p> Two opaque URIs with identical schemes and scheme-specific
151.1504 +     *   parts are ordered according to the ordering of their
151.1505 +     *   fragments. </p></li>
151.1506 +     *
151.1507 +     *   <li><p> Two hierarchical URIs with identical schemes are ordered
151.1508 +     *   according to the ordering of their authority components: </p>
151.1509 +     *
151.1510 +     *   <ul type=disc>
151.1511 +     *
151.1512 +     *     <li><p> If both authority components are server-based then the URIs
151.1513 +     *     are ordered according to their user-information components; if these
151.1514 +     *     components are identical then the URIs are ordered according to the
151.1515 +     *     ordering of their hosts, without regard to case; if the hosts are
151.1516 +     *     identical then the URIs are ordered according to the ordering of
151.1517 +     *     their ports. </p></li>
151.1518 +     *
151.1519 +     *     <li><p> If one or both authority components are registry-based then
151.1520 +     *     the URIs are ordered according to the ordering of their authority
151.1521 +     *     components. </p></li>
151.1522 +     *
151.1523 +     *   </ul></li>
151.1524 +     *
151.1525 +     *   <li><p> Finally, two hierarchical URIs with identical schemes and
151.1526 +     *   authority components are ordered according to the ordering of their
151.1527 +     *   paths; if their paths are identical then they are ordered according to
151.1528 +     *   the ordering of their queries; if the queries are identical then they
151.1529 +     *   are ordered according to the order of their fragments. </p></li>
151.1530 +     *
151.1531 +     * </ul>
151.1532 +     *
151.1533 +     * <p> This method satisfies the general contract of the {@link
151.1534 +     * java.lang.Comparable#compareTo(Object) Comparable.compareTo}
151.1535 +     * method. </p>
151.1536 +     *
151.1537 +     * @param   that
151.1538 +     *          The object to which this URI is to be compared
151.1539 +     *
151.1540 +     * @return  A negative integer, zero, or a positive integer as this URI is
151.1541 +     *          less than, equal to, or greater than the given URI
151.1542 +     *
151.1543 +     * @throws  ClassCastException
151.1544 +     *          If the given object is not a URI
151.1545 +     */
151.1546 +    public int compareTo(URI that) {
151.1547 +        int c;
151.1548 +
151.1549 +        if ((c = compareIgnoringCase(this.scheme, that.scheme)) != 0)
151.1550 +            return c;
151.1551 +
151.1552 +        if (this.isOpaque()) {
151.1553 +            if (that.isOpaque()) {
151.1554 +                // Both opaque
151.1555 +                if ((c = compare(this.schemeSpecificPart,
151.1556 +                                 that.schemeSpecificPart)) != 0)
151.1557 +                    return c;
151.1558 +                return compare(this.fragment, that.fragment);
151.1559 +            }
151.1560 +            return +1;                  // Opaque > hierarchical
151.1561 +        } else if (that.isOpaque()) {
151.1562 +            return -1;                  // Hierarchical < opaque
151.1563 +        }
151.1564 +
151.1565 +        // Hierarchical
151.1566 +        if ((this.host != null) && (that.host != null)) {
151.1567 +            // Both server-based
151.1568 +            if ((c = compare(this.userInfo, that.userInfo)) != 0)
151.1569 +                return c;
151.1570 +            if ((c = compareIgnoringCase(this.host, that.host)) != 0)
151.1571 +                return c;
151.1572 +            if ((c = this.port - that.port) != 0)
151.1573 +                return c;
151.1574 +        } else {
151.1575 +            // If one or both authorities are registry-based then we simply
151.1576 +            // compare them in the usual, case-sensitive way.  If one is
151.1577 +            // registry-based and one is server-based then the strings are
151.1578 +            // guaranteed to be unequal, hence the comparison will never return
151.1579 +            // zero and the compareTo and equals methods will remain
151.1580 +            // consistent.
151.1581 +            if ((c = compare(this.authority, that.authority)) != 0) return c;
151.1582 +        }
151.1583 +
151.1584 +        if ((c = compare(this.path, that.path)) != 0) return c;
151.1585 +        if ((c = compare(this.query, that.query)) != 0) return c;
151.1586 +        return compare(this.fragment, that.fragment);
151.1587 +    }
151.1588 +
151.1589 +    /**
151.1590 +     * Returns the content of this URI as a string.
151.1591 +     *
151.1592 +     * <p> If this URI was created by invoking one of the constructors in this
151.1593 +     * class then a string equivalent to the original input string, or to the
151.1594 +     * string computed from the originally-given components, as appropriate, is
151.1595 +     * returned.  Otherwise this URI was created by normalization, resolution,
151.1596 +     * or relativization, and so a string is constructed from this URI's
151.1597 +     * components according to the rules specified in <a
151.1598 +     * href="http://www.ietf.org/rfc/rfc2396.txt">RFC&nbsp;2396</a>,
151.1599 +     * section&nbsp;5.2, step&nbsp;7. </p>
151.1600 +     *
151.1601 +     * @return  The string form of this URI
151.1602 +     */
151.1603 +    public String toString() {
151.1604 +        defineString();
151.1605 +        return string;
151.1606 +    }
151.1607 +
151.1608 +    /**
151.1609 +     * Returns the content of this URI as a US-ASCII string.
151.1610 +     *
151.1611 +     * <p> If this URI does not contain any characters in the <i>other</i>
151.1612 +     * category then an invocation of this method will return the same value as
151.1613 +     * an invocation of the {@link #toString() toString} method.  Otherwise
151.1614 +     * this method works as if by invoking that method and then <a
151.1615 +     * href="#encode">encoding</a> the result.  </p>
151.1616 +     *
151.1617 +     * @return  The string form of this URI, encoded as needed
151.1618 +     *          so that it only contains characters in the US-ASCII
151.1619 +     *          charset
151.1620 +     */
151.1621 +    public String toASCIIString() {
151.1622 +        defineString();
151.1623 +        return encode(string);
151.1624 +    }
151.1625 +
151.1626 +
151.1627 +    // -- Serialization support --
151.1628 +
151.1629 +    /**
151.1630 +     * Saves the content of this URI to the given serial stream.
151.1631 +     *
151.1632 +     * <p> The only serializable field of a URI instance is its <tt>string</tt>
151.1633 +     * field.  That field is given a value, if it does not have one already,
151.1634 +     * and then the {@link java.io.ObjectOutputStream#defaultWriteObject()}
151.1635 +     * method of the given object-output stream is invoked. </p>
151.1636 +     *
151.1637 +     * @param  os  The object-output stream to which this object
151.1638 +     *             is to be written
151.1639 +     */
151.1640 +    private void writeObject(ObjectOutputStream os)
151.1641 +        throws IOException
151.1642 +    {
151.1643 +        defineString();
151.1644 +        os.defaultWriteObject();        // Writes the string field only
151.1645 +    }
151.1646 +
151.1647 +    /**
151.1648 +     * Reconstitutes a URI from the given serial stream.
151.1649 +     *
151.1650 +     * <p> The {@link java.io.ObjectInputStream#defaultReadObject()} method is
151.1651 +     * invoked to read the value of the <tt>string</tt> field.  The result is
151.1652 +     * then parsed in the usual way.
151.1653 +     *
151.1654 +     * @param  is  The object-input stream from which this object
151.1655 +     *             is being read
151.1656 +     */
151.1657 +    private void readObject(ObjectInputStream is)
151.1658 +        throws ClassNotFoundException, IOException
151.1659 +    {
151.1660 +        port = -1;                      // Argh
151.1661 +        is.defaultReadObject();
151.1662 +        try {
151.1663 +            new Parser(string).parse(false);
151.1664 +        } catch (URISyntaxException x) {
151.1665 +            IOException y = new InvalidObjectException("Invalid URI");
151.1666 +            y.initCause(x);
151.1667 +            throw y;
151.1668 +        }
151.1669 +    }
151.1670 +
151.1671 +
151.1672 +    // -- End of public methods --
151.1673 +
151.1674 +
151.1675 +    // -- Utility methods for string-field comparison and hashing --
151.1676 +
151.1677 +    // These methods return appropriate values for null string arguments,
151.1678 +    // thereby simplifying the equals, hashCode, and compareTo methods.
151.1679 +    //
151.1680 +    // The case-ignoring methods should only be applied to strings whose
151.1681 +    // characters are all known to be US-ASCII.  Because of this restriction,
151.1682 +    // these methods are faster than the similar methods in the String class.
151.1683 +
151.1684 +    // US-ASCII only
151.1685 +    private static int toLower(char c) {
151.1686 +        if ((c >= 'A') && (c <= 'Z'))
151.1687 +            return c + ('a' - 'A');
151.1688 +        return c;
151.1689 +    }
151.1690 +
151.1691 +    private static boolean equal(String s, String t) {
151.1692 +        if (s == t) return true;
151.1693 +        if ((s != null) && (t != null)) {
151.1694 +            if (s.length() != t.length())
151.1695 +                return false;
151.1696 +            if (s.indexOf('%') < 0)
151.1697 +                return s.equals(t);
151.1698 +            int n = s.length();
151.1699 +            for (int i = 0; i < n;) {
151.1700 +                char c = s.charAt(i);
151.1701 +                char d = t.charAt(i);
151.1702 +                if (c != '%') {
151.1703 +                    if (c != d)
151.1704 +                        return false;
151.1705 +                    i++;
151.1706 +                    continue;
151.1707 +                }
151.1708 +                i++;
151.1709 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
151.1710 +                    return false;
151.1711 +                i++;
151.1712 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
151.1713 +                    return false;
151.1714 +                i++;
151.1715 +            }
151.1716 +            return true;
151.1717 +        }
151.1718 +        return false;
151.1719 +    }
151.1720 +
151.1721 +    // US-ASCII only
151.1722 +    private static boolean equalIgnoringCase(String s, String t) {
151.1723 +        if (s == t) return true;
151.1724 +        if ((s != null) && (t != null)) {
151.1725 +            int n = s.length();
151.1726 +            if (t.length() != n)
151.1727 +                return false;
151.1728 +            for (int i = 0; i < n; i++) {
151.1729 +                if (toLower(s.charAt(i)) != toLower(t.charAt(i)))
151.1730 +                    return false;
151.1731 +            }
151.1732 +            return true;
151.1733 +        }
151.1734 +        return false;
151.1735 +    }
151.1736 +
151.1737 +    private static int hash(int hash, String s) {
151.1738 +        if (s == null) return hash;
151.1739 +        return hash * 127 + s.hashCode();
151.1740 +    }
151.1741 +
151.1742 +    // US-ASCII only
151.1743 +    private static int hashIgnoringCase(int hash, String s) {
151.1744 +        if (s == null) return hash;
151.1745 +        int h = hash;
151.1746 +        int n = s.length();
151.1747 +        for (int i = 0; i < n; i++)
151.1748 +            h = 31 * h + toLower(s.charAt(i));
151.1749 +        return h;
151.1750 +    }
151.1751 +
151.1752 +    private static int compare(String s, String t) {
151.1753 +        if (s == t) return 0;
151.1754 +        if (s != null) {
151.1755 +            if (t != null)
151.1756 +                return s.compareTo(t);
151.1757 +            else
151.1758 +                return +1;
151.1759 +        } else {
151.1760 +            return -1;
151.1761 +        }
151.1762 +    }
151.1763 +
151.1764 +    // US-ASCII only
151.1765 +    private static int compareIgnoringCase(String s, String t) {
151.1766 +        if (s == t) return 0;
151.1767 +        if (s != null) {
151.1768 +            if (t != null) {
151.1769 +                int sn = s.length();
151.1770 +                int tn = t.length();
151.1771 +                int n = sn < tn ? sn : tn;
151.1772 +                for (int i = 0; i < n; i++) {
151.1773 +                    int c = toLower(s.charAt(i)) - toLower(t.charAt(i));
151.1774 +                    if (c != 0)
151.1775 +                        return c;
151.1776 +                }
151.1777 +                return sn - tn;
151.1778 +            }
151.1779 +            return +1;
151.1780 +        } else {
151.1781 +            return -1;
151.1782 +        }
151.1783 +    }
151.1784 +
151.1785 +
151.1786 +    // -- String construction --
151.1787 +
151.1788 +    // If a scheme is given then the path, if given, must be absolute
151.1789 +    //
151.1790 +    private static void checkPath(String s, String scheme, String path)
151.1791 +        throws URISyntaxException
151.1792 +    {
151.1793 +        if (scheme != null) {
151.1794 +            if ((path != null)
151.1795 +                && ((path.length() > 0) && (path.charAt(0) != '/')))
151.1796 +                throw new URISyntaxException(s,
151.1797 +                                             "Relative path in absolute URI");
151.1798 +        }
151.1799 +    }
151.1800 +
151.1801 +    private void appendAuthority(StringBuffer sb,
151.1802 +                                 String authority,
151.1803 +                                 String userInfo,
151.1804 +                                 String host,
151.1805 +                                 int port)
151.1806 +    {
151.1807 +        if (host != null) {
151.1808 +            sb.append("//");
151.1809 +            if (userInfo != null) {
151.1810 +                sb.append(quote(userInfo, L_USERINFO, H_USERINFO));
151.1811 +                sb.append('@');
151.1812 +            }
151.1813 +            boolean needBrackets = ((host.indexOf(':') >= 0)
151.1814 +                                    && !host.startsWith("[")
151.1815 +                                    && !host.endsWith("]"));
151.1816 +            if (needBrackets) sb.append('[');
151.1817 +            sb.append(host);
151.1818 +            if (needBrackets) sb.append(']');
151.1819 +            if (port != -1) {
151.1820 +                sb.append(':');
151.1821 +                sb.append(port);
151.1822 +            }
151.1823 +        } else if (authority != null) {
151.1824 +            sb.append("//");
151.1825 +            if (authority.startsWith("[")) {
151.1826 +                // authority should (but may not) contain an embedded IPv6 address
151.1827 +                int end = authority.indexOf("]");
151.1828 +                String doquote = authority, dontquote = "";
151.1829 +                if (end != -1 && authority.indexOf(":") != -1) {
151.1830 +                    // the authority contains an IPv6 address
151.1831 +                    if (end == authority.length()) {
151.1832 +                        dontquote = authority;
151.1833 +                        doquote = "";
151.1834 +                    } else {
151.1835 +                        dontquote = authority.substring(0 , end + 1);
151.1836 +                        doquote = authority.substring(end + 1);
151.1837 +                    }
151.1838 +                }
151.1839 +                sb.append(dontquote);
151.1840 +                sb.append(quote(doquote,
151.1841 +                            L_REG_NAME | L_SERVER,
151.1842 +                            H_REG_NAME | H_SERVER));
151.1843 +            } else {
151.1844 +                sb.append(quote(authority,
151.1845 +                            L_REG_NAME | L_SERVER,
151.1846 +                            H_REG_NAME | H_SERVER));
151.1847 +            }
151.1848 +        }
151.1849 +    }
151.1850 +
151.1851 +    private void appendSchemeSpecificPart(StringBuffer sb,
151.1852 +                                          String opaquePart,
151.1853 +                                          String authority,
151.1854 +                                          String userInfo,
151.1855 +                                          String host,
151.1856 +                                          int port,
151.1857 +                                          String path,
151.1858 +                                          String query)
151.1859 +    {
151.1860 +        if (opaquePart != null) {
151.1861 +            /* check if SSP begins with an IPv6 address
151.1862 +             * because we must not quote a literal IPv6 address
151.1863 +             */
151.1864 +            if (opaquePart.startsWith("//[")) {
151.1865 +                int end =  opaquePart.indexOf("]");
151.1866 +                if (end != -1 && opaquePart.indexOf(":")!=-1) {
151.1867 +                    String doquote, dontquote;
151.1868 +                    if (end == opaquePart.length()) {
151.1869 +                        dontquote = opaquePart;
151.1870 +                        doquote = "";
151.1871 +                    } else {
151.1872 +                        dontquote = opaquePart.substring(0,end+1);
151.1873 +                        doquote = opaquePart.substring(end+1);
151.1874 +                    }
151.1875 +                    sb.append (dontquote);
151.1876 +                    sb.append(quote(doquote, L_URIC, H_URIC));
151.1877 +                }
151.1878 +            } else {
151.1879 +                sb.append(quote(opaquePart, L_URIC, H_URIC));
151.1880 +            }
151.1881 +        } else {
151.1882 +            appendAuthority(sb, authority, userInfo, host, port);
151.1883 +            if (path != null)
151.1884 +                sb.append(quote(path, L_PATH, H_PATH));
151.1885 +            if (query != null) {
151.1886 +                sb.append('?');
151.1887 +                sb.append(quote(query, L_URIC, H_URIC));
151.1888 +            }
151.1889 +        }
151.1890 +    }
151.1891 +
151.1892 +    private void appendFragment(StringBuffer sb, String fragment) {
151.1893 +        if (fragment != null) {
151.1894 +            sb.append('#');
151.1895 +            sb.append(quote(fragment, L_URIC, H_URIC));
151.1896 +        }
151.1897 +    }
151.1898 +
151.1899 +    private String toString(String scheme,
151.1900 +                            String opaquePart,
151.1901 +                            String authority,
151.1902 +                            String userInfo,
151.1903 +                            String host,
151.1904 +                            int port,
151.1905 +                            String path,
151.1906 +                            String query,
151.1907 +                            String fragment)
151.1908 +    {
151.1909 +        StringBuffer sb = new StringBuffer();
151.1910 +        if (scheme != null) {
151.1911 +            sb.append(scheme);
151.1912 +            sb.append(':');
151.1913 +        }
151.1914 +        appendSchemeSpecificPart(sb, opaquePart,
151.1915 +                                 authority, userInfo, host, port,
151.1916 +                                 path, query);
151.1917 +        appendFragment(sb, fragment);
151.1918 +        return sb.toString();
151.1919 +    }
151.1920 +
151.1921 +    private void defineSchemeSpecificPart() {
151.1922 +        if (schemeSpecificPart != null) return;
151.1923 +        StringBuffer sb = new StringBuffer();
151.1924 +        appendSchemeSpecificPart(sb, null, getAuthority(), getUserInfo(),
151.1925 +                                 host, port, getPath(), getQuery());
151.1926 +        if (sb.length() == 0) return;
151.1927 +        schemeSpecificPart = sb.toString();
151.1928 +    }
151.1929 +
151.1930 +    private void defineString() {
151.1931 +        if (string != null) return;
151.1932 +
151.1933 +        StringBuffer sb = new StringBuffer();
151.1934 +        if (scheme != null) {
151.1935 +            sb.append(scheme);
151.1936 +            sb.append(':');
151.1937 +        }
151.1938 +        if (isOpaque()) {
151.1939 +            sb.append(schemeSpecificPart);
151.1940 +        } else {
151.1941 +            if (host != null) {
151.1942 +                sb.append("//");
151.1943 +                if (userInfo != null) {
151.1944 +                    sb.append(userInfo);
151.1945 +                    sb.append('@');
151.1946 +                }
151.1947 +                boolean needBrackets = ((host.indexOf(':') >= 0)
151.1948 +                                    && !host.startsWith("[")
151.1949 +                                    && !host.endsWith("]"));
151.1950 +                if (needBrackets) sb.append('[');
151.1951 +                sb.append(host);
151.1952 +                if (needBrackets) sb.append(']');
151.1953 +                if (port != -1) {
151.1954 +                    sb.append(':');
151.1955 +                    sb.append(port);
151.1956 +                }
151.1957 +            } else if (authority != null) {
151.1958 +                sb.append("//");
151.1959 +                sb.append(authority);
151.1960 +            }
151.1961 +            if (path != null)
151.1962 +                sb.append(path);
151.1963 +            if (query != null) {
151.1964 +                sb.append('?');
151.1965 +                sb.append(query);
151.1966 +            }
151.1967 +        }
151.1968 +        if (fragment != null) {
151.1969 +            sb.append('#');
151.1970 +            sb.append(fragment);
151.1971 +        }
151.1972 +        string = sb.toString();
151.1973 +    }
151.1974 +
151.1975 +
151.1976 +    // -- Normalization, resolution, and relativization --
151.1977 +
151.1978 +    // RFC2396 5.2 (6)
151.1979 +    private static String resolvePath(String base, String child,
151.1980 +                                      boolean absolute)
151.1981 +    {
151.1982 +        int i = base.lastIndexOf('/');
151.1983 +        int cn = child.length();
151.1984 +        String path = "";
151.1985 +
151.1986 +        if (cn == 0) {
151.1987 +            // 5.2 (6a)
151.1988 +            if (i >= 0)
151.1989 +                path = base.substring(0, i + 1);
151.1990 +        } else {
151.1991 +            StringBuffer sb = new StringBuffer(base.length() + cn);
151.1992 +            // 5.2 (6a)
151.1993 +            if (i >= 0)
151.1994 +                sb.append(base.substring(0, i + 1));
151.1995 +            // 5.2 (6b)
151.1996 +            sb.append(child);
151.1997 +            path = sb.toString();
151.1998 +        }
151.1999 +
151.2000 +        // 5.2 (6c-f)
151.2001 +        String np = normalize(path);
151.2002 +
151.2003 +        // 5.2 (6g): If the result is absolute but the path begins with "../",
151.2004 +        // then we simply leave the path as-is
151.2005 +
151.2006 +        return np;
151.2007 +    }
151.2008 +
151.2009 +    // RFC2396 5.2
151.2010 +    private static URI resolve(URI base, URI child) {
151.2011 +        // check if child if opaque first so that NPE is thrown
151.2012 +        // if child is null.
151.2013 +        if (child.isOpaque() || base.isOpaque())
151.2014 +            return child;
151.2015 +
151.2016 +        // 5.2 (2): Reference to current document (lone fragment)
151.2017 +        if ((child.scheme == null) && (child.authority == null)
151.2018 +            && child.path.equals("") && (child.fragment != null)
151.2019 +            && (child.query == null)) {
151.2020 +            if ((base.fragment != null)
151.2021 +                && child.fragment.equals(base.fragment)) {
151.2022 +                return base;
151.2023 +            }
151.2024 +            URI ru = new URI();
151.2025 +            ru.scheme = base.scheme;
151.2026 +            ru.authority = base.authority;
151.2027 +            ru.userInfo = base.userInfo;
151.2028 +            ru.host = base.host;
151.2029 +            ru.port = base.port;
151.2030 +            ru.path = base.path;
151.2031 +            ru.fragment = child.fragment;
151.2032 +            ru.query = base.query;
151.2033 +            return ru;
151.2034 +        }
151.2035 +
151.2036 +        // 5.2 (3): Child is absolute
151.2037 +        if (child.scheme != null)
151.2038 +            return child;
151.2039 +
151.2040 +        URI ru = new URI();             // Resolved URI
151.2041 +        ru.scheme = base.scheme;
151.2042 +        ru.query = child.query;
151.2043 +        ru.fragment = child.fragment;
151.2044 +
151.2045 +        // 5.2 (4): Authority
151.2046 +        if (child.authority == null) {
151.2047 +            ru.authority = base.authority;
151.2048 +            ru.host = base.host;
151.2049 +            ru.userInfo = base.userInfo;
151.2050 +            ru.port = base.port;
151.2051 +
151.2052 +            String cp = (child.path == null) ? "" : child.path;
151.2053 +            if ((cp.length() > 0) && (cp.charAt(0) == '/')) {
151.2054 +                // 5.2 (5): Child path is absolute
151.2055 +                ru.path = child.path;
151.2056 +            } else {
151.2057 +                // 5.2 (6): Resolve relative path
151.2058 +                ru.path = resolvePath(base.path, cp, base.isAbsolute());
151.2059 +            }
151.2060 +        } else {
151.2061 +            ru.authority = child.authority;
151.2062 +            ru.host = child.host;
151.2063 +            ru.userInfo = child.userInfo;
151.2064 +            ru.host = child.host;
151.2065 +            ru.port = child.port;
151.2066 +            ru.path = child.path;
151.2067 +        }
151.2068 +
151.2069 +        // 5.2 (7): Recombine (nothing to do here)
151.2070 +        return ru;
151.2071 +    }
151.2072 +
151.2073 +    // If the given URI's path is normal then return the URI;
151.2074 +    // o.w., return a new URI containing the normalized path.
151.2075 +    //
151.2076 +    private static URI normalize(URI u) {
151.2077 +        if (u.isOpaque() || (u.path == null) || (u.path.length() == 0))
151.2078 +            return u;
151.2079 +
151.2080 +        String np = normalize(u.path);
151.2081 +        if (np == u.path)
151.2082 +            return u;
151.2083 +
151.2084 +        URI v = new URI();
151.2085 +        v.scheme = u.scheme;
151.2086 +        v.fragment = u.fragment;
151.2087 +        v.authority = u.authority;
151.2088 +        v.userInfo = u.userInfo;
151.2089 +        v.host = u.host;
151.2090 +        v.port = u.port;
151.2091 +        v.path = np;
151.2092 +        v.query = u.query;
151.2093 +        return v;
151.2094 +    }
151.2095 +
151.2096 +    // If both URIs are hierarchical, their scheme and authority components are
151.2097 +    // identical, and the base path is a prefix of the child's path, then
151.2098 +    // return a relative URI that, when resolved against the base, yields the
151.2099 +    // child; otherwise, return the child.
151.2100 +    //
151.2101 +    private static URI relativize(URI base, URI child) {
151.2102 +        // check if child if opaque first so that NPE is thrown
151.2103 +        // if child is null.
151.2104 +        if (child.isOpaque() || base.isOpaque())
151.2105 +            return child;
151.2106 +        if (!equalIgnoringCase(base.scheme, child.scheme)
151.2107 +            || !equal(base.authority, child.authority))
151.2108 +            return child;
151.2109 +
151.2110 +        String bp = normalize(base.path);
151.2111 +        String cp = normalize(child.path);
151.2112 +        if (!bp.equals(cp)) {
151.2113 +            if (!bp.endsWith("/"))
151.2114 +                bp = bp + "/";
151.2115 +            if (!cp.startsWith(bp))
151.2116 +                return child;
151.2117 +        }
151.2118 +
151.2119 +        URI v = new URI();
151.2120 +        v.path = cp.substring(bp.length());
151.2121 +        v.query = child.query;
151.2122 +        v.fragment = child.fragment;
151.2123 +        return v;
151.2124 +    }
151.2125 +
151.2126 +
151.2127 +
151.2128 +    // -- Path normalization --
151.2129 +
151.2130 +    // The following algorithm for path normalization avoids the creation of a
151.2131 +    // string object for each segment, as well as the use of a string buffer to
151.2132 +    // compute the final result, by using a single char array and editing it in
151.2133 +    // place.  The array is first split into segments, replacing each slash
151.2134 +    // with '\0' and creating a segment-index array, each element of which is
151.2135 +    // the index of the first char in the corresponding segment.  We then walk
151.2136 +    // through both arrays, removing ".", "..", and other segments as necessary
151.2137 +    // by setting their entries in the index array to -1.  Finally, the two
151.2138 +    // arrays are used to rejoin the segments and compute the final result.
151.2139 +    //
151.2140 +    // This code is based upon src/solaris/native/java/io/canonicalize_md.c
151.2141 +
151.2142 +
151.2143 +    // Check the given path to see if it might need normalization.  A path
151.2144 +    // might need normalization if it contains duplicate slashes, a "."
151.2145 +    // segment, or a ".." segment.  Return -1 if no further normalization is
151.2146 +    // possible, otherwise return the number of segments found.
151.2147 +    //
151.2148 +    // This method takes a string argument rather than a char array so that
151.2149 +    // this test can be performed without invoking path.toCharArray().
151.2150 +    //
151.2151 +    static private int needsNormalization(String path) {
151.2152 +        boolean normal = true;
151.2153 +        int ns = 0;                     // Number of segments
151.2154 +        int end = path.length() - 1;    // Index of last char in path
151.2155 +        int p = 0;                      // Index of next char in path
151.2156 +
151.2157 +        // Skip initial slashes
151.2158 +        while (p <= end) {
151.2159 +            if (path.charAt(p) != '/') break;
151.2160 +            p++;
151.2161 +        }
151.2162 +        if (p > 1) normal = false;
151.2163 +
151.2164 +        // Scan segments
151.2165 +        while (p <= end) {
151.2166 +
151.2167 +            // Looking at "." or ".." ?
151.2168 +            if ((path.charAt(p) == '.')
151.2169 +                && ((p == end)
151.2170 +                    || ((path.charAt(p + 1) == '/')
151.2171 +                        || ((path.charAt(p + 1) == '.')
151.2172 +                            && ((p + 1 == end)
151.2173 +                                || (path.charAt(p + 2) == '/')))))) {
151.2174 +                normal = false;
151.2175 +            }
151.2176 +            ns++;
151.2177 +
151.2178 +            // Find beginning of next segment
151.2179 +            while (p <= end) {
151.2180 +                if (path.charAt(p++) != '/')
151.2181 +                    continue;
151.2182 +
151.2183 +                // Skip redundant slashes
151.2184 +                while (p <= end) {
151.2185 +                    if (path.charAt(p) != '/') break;
151.2186 +                    normal = false;
151.2187 +                    p++;
151.2188 +                }
151.2189 +
151.2190 +                break;
151.2191 +            }
151.2192 +        }
151.2193 +
151.2194 +        return normal ? -1 : ns;
151.2195 +    }
151.2196 +
151.2197 +
151.2198 +    // Split the given path into segments, replacing slashes with nulls and
151.2199 +    // filling in the given segment-index array.
151.2200 +    //
151.2201 +    // Preconditions:
151.2202 +    //   segs.length == Number of segments in path
151.2203 +    //
151.2204 +    // Postconditions:
151.2205 +    //   All slashes in path replaced by '\0'
151.2206 +    //   segs[i] == Index of first char in segment i (0 <= i < segs.length)
151.2207 +    //
151.2208 +    static private void split(char[] path, int[] segs) {
151.2209 +        int end = path.length - 1;      // Index of last char in path
151.2210 +        int p = 0;                      // Index of next char in path
151.2211 +        int i = 0;                      // Index of current segment
151.2212 +
151.2213 +        // Skip initial slashes
151.2214 +        while (p <= end) {
151.2215 +            if (path[p] != '/') break;
151.2216 +            path[p] = '\0';
151.2217 +            p++;
151.2218 +        }
151.2219 +
151.2220 +        while (p <= end) {
151.2221 +
151.2222 +            // Note start of segment
151.2223 +            segs[i++] = p++;
151.2224 +
151.2225 +            // Find beginning of next segment
151.2226 +            while (p <= end) {
151.2227 +                if (path[p++] != '/')
151.2228 +                    continue;
151.2229 +                path[p - 1] = '\0';
151.2230 +
151.2231 +                // Skip redundant slashes
151.2232 +                while (p <= end) {
151.2233 +                    if (path[p] != '/') break;
151.2234 +                    path[p++] = '\0';
151.2235 +                }
151.2236 +                break;
151.2237 +            }
151.2238 +        }
151.2239 +
151.2240 +        if (i != segs.length)
151.2241 +            throw new InternalError();  // ASSERT
151.2242 +    }
151.2243 +
151.2244 +
151.2245 +    // Join the segments in the given path according to the given segment-index
151.2246 +    // array, ignoring those segments whose index entries have been set to -1,
151.2247 +    // and inserting slashes as needed.  Return the length of the resulting
151.2248 +    // path.
151.2249 +    //
151.2250 +    // Preconditions:
151.2251 +    //   segs[i] == -1 implies segment i is to be ignored
151.2252 +    //   path computed by split, as above, with '\0' having replaced '/'
151.2253 +    //
151.2254 +    // Postconditions:
151.2255 +    //   path[0] .. path[return value] == Resulting path
151.2256 +    //
151.2257 +    static private int join(char[] path, int[] segs) {
151.2258 +        int ns = segs.length;           // Number of segments
151.2259 +        int end = path.length - 1;      // Index of last char in path
151.2260 +        int p = 0;                      // Index of next path char to write
151.2261 +
151.2262 +        if (path[p] == '\0') {
151.2263 +            // Restore initial slash for absolute paths
151.2264 +            path[p++] = '/';
151.2265 +        }
151.2266 +
151.2267 +        for (int i = 0; i < ns; i++) {
151.2268 +            int q = segs[i];            // Current segment
151.2269 +            if (q == -1)
151.2270 +                // Ignore this segment
151.2271 +                continue;
151.2272 +
151.2273 +            if (p == q) {
151.2274 +                // We're already at this segment, so just skip to its end
151.2275 +                while ((p <= end) && (path[p] != '\0'))
151.2276 +                    p++;
151.2277 +                if (p <= end) {
151.2278 +                    // Preserve trailing slash
151.2279 +                    path[p++] = '/';
151.2280 +                }
151.2281 +            } else if (p < q) {
151.2282 +                // Copy q down to p
151.2283 +                while ((q <= end) && (path[q] != '\0'))
151.2284 +                    path[p++] = path[q++];
151.2285 +                if (q <= end) {
151.2286 +                    // Preserve trailing slash
151.2287 +                    path[p++] = '/';
151.2288 +                }
151.2289 +            } else
151.2290 +                throw new InternalError(); // ASSERT false
151.2291 +        }
151.2292 +
151.2293 +        return p;
151.2294 +    }
151.2295 +
151.2296 +
151.2297 +    // Remove "." segments from the given path, and remove segment pairs
151.2298 +    // consisting of a non-".." segment followed by a ".." segment.
151.2299 +    //
151.2300 +    private static void removeDots(char[] path, int[] segs) {
151.2301 +        int ns = segs.length;
151.2302 +        int end = path.length - 1;
151.2303 +
151.2304 +        for (int i = 0; i < ns; i++) {
151.2305 +            int dots = 0;               // Number of dots found (0, 1, or 2)
151.2306 +
151.2307 +            // Find next occurrence of "." or ".."
151.2308 +            do {
151.2309 +                int p = segs[i];
151.2310 +                if (path[p] == '.') {
151.2311 +                    if (p == end) {
151.2312 +                        dots = 1;
151.2313 +                        break;
151.2314 +                    } else if (path[p + 1] == '\0') {
151.2315 +                        dots = 1;
151.2316 +                        break;
151.2317 +                    } else if ((path[p + 1] == '.')
151.2318 +                               && ((p + 1 == end)
151.2319 +                                   || (path[p + 2] == '\0'))) {
151.2320 +                        dots = 2;
151.2321 +                        break;
151.2322 +                    }
151.2323 +                }
151.2324 +                i++;
151.2325 +            } while (i < ns);
151.2326 +            if ((i > ns) || (dots == 0))
151.2327 +                break;
151.2328 +
151.2329 +            if (dots == 1) {
151.2330 +                // Remove this occurrence of "."
151.2331 +                segs[i] = -1;
151.2332 +            } else {
151.2333 +                // If there is a preceding non-".." segment, remove both that
151.2334 +                // segment and this occurrence of ".."; otherwise, leave this
151.2335 +                // ".." segment as-is.
151.2336 +                int j;
151.2337 +                for (j = i - 1; j >= 0; j--) {
151.2338 +                    if (segs[j] != -1) break;
151.2339 +                }
151.2340 +                if (j >= 0) {
151.2341 +                    int q = segs[j];
151.2342 +                    if (!((path[q] == '.')
151.2343 +                          && (path[q + 1] == '.')
151.2344 +                          && (path[q + 2] == '\0'))) {
151.2345 +                        segs[i] = -1;
151.2346 +                        segs[j] = -1;
151.2347 +                    }
151.2348 +                }
151.2349 +            }
151.2350 +        }
151.2351 +    }
151.2352 +
151.2353 +
151.2354 +    // DEVIATION: If the normalized path is relative, and if the first
151.2355 +    // segment could be parsed as a scheme name, then prepend a "." segment
151.2356 +    //
151.2357 +    private static void maybeAddLeadingDot(char[] path, int[] segs) {
151.2358 +
151.2359 +        if (path[0] == '\0')
151.2360 +            // The path is absolute
151.2361 +            return;
151.2362 +
151.2363 +        int ns = segs.length;
151.2364 +        int f = 0;                      // Index of first segment
151.2365 +        while (f < ns) {
151.2366 +            if (segs[f] >= 0)
151.2367 +                break;
151.2368 +            f++;
151.2369 +        }
151.2370 +        if ((f >= ns) || (f == 0))
151.2371 +            // The path is empty, or else the original first segment survived,
151.2372 +            // in which case we already know that no leading "." is needed
151.2373 +            return;
151.2374 +
151.2375 +        int p = segs[f];
151.2376 +        while ((p < path.length) && (path[p] != ':') && (path[p] != '\0')) p++;
151.2377 +        if (p >= path.length || path[p] == '\0')
151.2378 +            // No colon in first segment, so no "." needed
151.2379 +            return;
151.2380 +
151.2381 +        // At this point we know that the first segment is unused,
151.2382 +        // hence we can insert a "." segment at that position
151.2383 +        path[0] = '.';
151.2384 +        path[1] = '\0';
151.2385 +        segs[0] = 0;
151.2386 +    }
151.2387 +
151.2388 +
151.2389 +    // Normalize the given path string.  A normal path string has no empty
151.2390 +    // segments (i.e., occurrences of "//"), no segments equal to ".", and no
151.2391 +    // segments equal to ".." that are preceded by a segment not equal to "..".
151.2392 +    // In contrast to Unix-style pathname normalization, for URI paths we
151.2393 +    // always retain trailing slashes.
151.2394 +    //
151.2395 +    private static String normalize(String ps) {
151.2396 +
151.2397 +        // Does this path need normalization?
151.2398 +        int ns = needsNormalization(ps);        // Number of segments
151.2399 +        if (ns < 0)
151.2400 +            // Nope -- just return it
151.2401 +            return ps;
151.2402 +
151.2403 +        char[] path = ps.toCharArray();         // Path in char-array form
151.2404 +
151.2405 +        // Split path into segments
151.2406 +        int[] segs = new int[ns];               // Segment-index array
151.2407 +        split(path, segs);
151.2408 +
151.2409 +        // Remove dots
151.2410 +        removeDots(path, segs);
151.2411 +
151.2412 +        // Prevent scheme-name confusion
151.2413 +        maybeAddLeadingDot(path, segs);
151.2414 +
151.2415 +        // Join the remaining segments and return the result
151.2416 +        String s = new String(path, 0, join(path, segs));
151.2417 +        if (s.equals(ps)) {
151.2418 +            // string was already normalized
151.2419 +            return ps;
151.2420 +        }
151.2421 +        return s;
151.2422 +    }
151.2423 +
151.2424 +
151.2425 +
151.2426 +    // -- Character classes for parsing --
151.2427 +
151.2428 +    // RFC2396 precisely specifies which characters in the US-ASCII charset are
151.2429 +    // permissible in the various components of a URI reference.  We here
151.2430 +    // define a set of mask pairs to aid in enforcing these restrictions.  Each
151.2431 +    // mask pair consists of two longs, a low mask and a high mask.  Taken
151.2432 +    // together they represent a 128-bit mask, where bit i is set iff the
151.2433 +    // character with value i is permitted.
151.2434 +    //
151.2435 +    // This approach is more efficient than sequentially searching arrays of
151.2436 +    // permitted characters.  It could be made still more efficient by
151.2437 +    // precompiling the mask information so that a character's presence in a
151.2438 +    // given mask could be determined by a single table lookup.
151.2439 +
151.2440 +    // Compute the low-order mask for the characters in the given string
151.2441 +    private static long lowMask(String chars) {
151.2442 +        int n = chars.length();
151.2443 +        long m = 0;
151.2444 +        for (int i = 0; i < n; i++) {
151.2445 +            char c = chars.charAt(i);
151.2446 +            if (c < 64)
151.2447 +                m |= (1L << c);
151.2448 +        }
151.2449 +        return m;
151.2450 +    }
151.2451 +
151.2452 +    // Compute the high-order mask for the characters in the given string
151.2453 +    private static long highMask(String chars) {
151.2454 +        int n = chars.length();
151.2455 +        long m = 0;
151.2456 +        for (int i = 0; i < n; i++) {
151.2457 +            char c = chars.charAt(i);
151.2458 +            if ((c >= 64) && (c < 128))
151.2459 +                m |= (1L << (c - 64));
151.2460 +        }
151.2461 +        return m;
151.2462 +    }
151.2463 +
151.2464 +    // Compute a low-order mask for the characters
151.2465 +    // between first and last, inclusive
151.2466 +    private static long lowMask(char first, char last) {
151.2467 +        long m = 0;
151.2468 +        int f = Math.max(Math.min(first, 63), 0);
151.2469 +        int l = Math.max(Math.min(last, 63), 0);
151.2470 +        for (int i = f; i <= l; i++)
151.2471 +            m |= 1L << i;
151.2472 +        return m;
151.2473 +    }
151.2474 +
151.2475 +    // Compute a high-order mask for the characters
151.2476 +    // between first and last, inclusive
151.2477 +    private static long highMask(char first, char last) {
151.2478 +        long m = 0;
151.2479 +        int f = Math.max(Math.min(first, 127), 64) - 64;
151.2480 +        int l = Math.max(Math.min(last, 127), 64) - 64;
151.2481 +        for (int i = f; i <= l; i++)
151.2482 +            m |= 1L << i;
151.2483 +        return m;
151.2484 +    }
151.2485 +
151.2486 +    // Tell whether the given character is permitted by the given mask pair
151.2487 +    private static boolean match(char c, long lowMask, long highMask) {
151.2488 +        if (c == 0) // 0 doesn't have a slot in the mask. So, it never matches.
151.2489 +            return false;
151.2490 +        if (c < 64)
151.2491 +            return ((1L << c) & lowMask) != 0;
151.2492 +        if (c < 128)
151.2493 +            return ((1L << (c - 64)) & highMask) != 0;
151.2494 +        return false;
151.2495 +    }
151.2496 +
151.2497 +    // Character-class masks, in reverse order from RFC2396 because
151.2498 +    // initializers for static fields cannot make forward references.
151.2499 +
151.2500 +    // digit    = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" |
151.2501 +    //            "8" | "9"
151.2502 +    private static final long L_DIGIT = lowMask('0', '9');
151.2503 +    private static final long H_DIGIT = 0L;
151.2504 +
151.2505 +    // upalpha  = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" |
151.2506 +    //            "J" | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" |
151.2507 +    //            "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
151.2508 +    private static final long L_UPALPHA = 0L;
151.2509 +    private static final long H_UPALPHA = highMask('A', 'Z');
151.2510 +
151.2511 +    // lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" |
151.2512 +    //            "j" | "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" |
151.2513 +    //            "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
151.2514 +    private static final long L_LOWALPHA = 0L;
151.2515 +    private static final long H_LOWALPHA = highMask('a', 'z');
151.2516 +
151.2517 +    // alpha         = lowalpha | upalpha
151.2518 +    private static final long L_ALPHA = L_LOWALPHA | L_UPALPHA;
151.2519 +    private static final long H_ALPHA = H_LOWALPHA | H_UPALPHA;
151.2520 +
151.2521 +    // alphanum      = alpha | digit
151.2522 +    private static final long L_ALPHANUM = L_DIGIT | L_ALPHA;
151.2523 +    private static final long H_ALPHANUM = H_DIGIT | H_ALPHA;
151.2524 +
151.2525 +    // hex           = digit | "A" | "B" | "C" | "D" | "E" | "F" |
151.2526 +    //                         "a" | "b" | "c" | "d" | "e" | "f"
151.2527 +    private static final long L_HEX = L_DIGIT;
151.2528 +    private static final long H_HEX = highMask('A', 'F') | highMask('a', 'f');
151.2529 +
151.2530 +    // mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
151.2531 +    //                 "(" | ")"
151.2532 +    private static final long L_MARK = lowMask("-_.!~*'()");
151.2533 +    private static final long H_MARK = highMask("-_.!~*'()");
151.2534 +
151.2535 +    // unreserved    = alphanum | mark
151.2536 +    private static final long L_UNRESERVED = L_ALPHANUM | L_MARK;
151.2537 +    private static final long H_UNRESERVED = H_ALPHANUM | H_MARK;
151.2538 +
151.2539 +    // reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
151.2540 +    //                 "$" | "," | "[" | "]"
151.2541 +    // Added per RFC2732: "[", "]"
151.2542 +    private static final long L_RESERVED = lowMask(";/?:@&=+$,[]");
151.2543 +    private static final long H_RESERVED = highMask(";/?:@&=+$,[]");
151.2544 +
151.2545 +    // The zero'th bit is used to indicate that escape pairs and non-US-ASCII
151.2546 +    // characters are allowed; this is handled by the scanEscape method below.
151.2547 +    private static final long L_ESCAPED = 1L;
151.2548 +    private static final long H_ESCAPED = 0L;
151.2549 +
151.2550 +    // uric          = reserved | unreserved | escaped
151.2551 +    private static final long L_URIC = L_RESERVED | L_UNRESERVED | L_ESCAPED;
151.2552 +    private static final long H_URIC = H_RESERVED | H_UNRESERVED | H_ESCAPED;
151.2553 +
151.2554 +    // pchar         = unreserved | escaped |
151.2555 +    //                 ":" | "@" | "&" | "=" | "+" | "$" | ","
151.2556 +    private static final long L_PCHAR
151.2557 +        = L_UNRESERVED | L_ESCAPED | lowMask(":@&=+$,");
151.2558 +    private static final long H_PCHAR
151.2559 +        = H_UNRESERVED | H_ESCAPED | highMask(":@&=+$,");
151.2560 +
151.2561 +    // All valid path characters
151.2562 +    private static final long L_PATH = L_PCHAR | lowMask(";/");
151.2563 +    private static final long H_PATH = H_PCHAR | highMask(";/");
151.2564 +
151.2565 +    // Dash, for use in domainlabel and toplabel
151.2566 +    private static final long L_DASH = lowMask("-");
151.2567 +    private static final long H_DASH = highMask("-");
151.2568 +
151.2569 +    // Dot, for use in hostnames
151.2570 +    private static final long L_DOT = lowMask(".");
151.2571 +    private static final long H_DOT = highMask(".");
151.2572 +
151.2573 +    // userinfo      = *( unreserved | escaped |
151.2574 +    //                    ";" | ":" | "&" | "=" | "+" | "$" | "," )
151.2575 +    private static final long L_USERINFO
151.2576 +        = L_UNRESERVED | L_ESCAPED | lowMask(";:&=+$,");
151.2577 +    private static final long H_USERINFO
151.2578 +        = H_UNRESERVED | H_ESCAPED | highMask(";:&=+$,");
151.2579 +
151.2580 +    // reg_name      = 1*( unreserved | escaped | "$" | "," |
151.2581 +    //                     ";" | ":" | "@" | "&" | "=" | "+" )
151.2582 +    private static final long L_REG_NAME
151.2583 +        = L_UNRESERVED | L_ESCAPED | lowMask("$,;:@&=+");
151.2584 +    private static final long H_REG_NAME
151.2585 +        = H_UNRESERVED | H_ESCAPED | highMask("$,;:@&=+");
151.2586 +
151.2587 +    // All valid characters for server-based authorities
151.2588 +    private static final long L_SERVER
151.2589 +        = L_USERINFO | L_ALPHANUM | L_DASH | lowMask(".:@[]");
151.2590 +    private static final long H_SERVER
151.2591 +        = H_USERINFO | H_ALPHANUM | H_DASH | highMask(".:@[]");
151.2592 +
151.2593 +    // Special case of server authority that represents an IPv6 address
151.2594 +    // In this case, a % does not signify an escape sequence
151.2595 +    private static final long L_SERVER_PERCENT
151.2596 +        = L_SERVER | lowMask("%");
151.2597 +    private static final long H_SERVER_PERCENT
151.2598 +        = H_SERVER | highMask("%");
151.2599 +    private static final long L_LEFT_BRACKET = lowMask("[");
151.2600 +    private static final long H_LEFT_BRACKET = highMask("[");
151.2601 +
151.2602 +    // scheme        = alpha *( alpha | digit | "+" | "-" | "." )
151.2603 +    private static final long L_SCHEME = L_ALPHA | L_DIGIT | lowMask("+-.");
151.2604 +    private static final long H_SCHEME = H_ALPHA | H_DIGIT | highMask("+-.");
151.2605 +
151.2606 +    // uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
151.2607 +    //                 "&" | "=" | "+" | "$" | ","
151.2608 +    private static final long L_URIC_NO_SLASH
151.2609 +        = L_UNRESERVED | L_ESCAPED | lowMask(";?:@&=+$,");
151.2610 +    private static final long H_URIC_NO_SLASH
151.2611 +        = H_UNRESERVED | H_ESCAPED | highMask(";?:@&=+$,");
151.2612 +
151.2613 +
151.2614 +    // -- Escaping and encoding --
151.2615 +
151.2616 +    private final static char[] hexDigits = {
151.2617 +        '0', '1', '2', '3', '4', '5', '6', '7',
151.2618 +        '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
151.2619 +    };
151.2620 +
151.2621 +    private static void appendEscape(StringBuffer sb, byte b) {
151.2622 +        sb.append('%');
151.2623 +        sb.append(hexDigits[(b >> 4) & 0x0f]);
151.2624 +        sb.append(hexDigits[(b >> 0) & 0x0f]);
151.2625 +    }
151.2626 +
151.2627 +    private static void appendEncoded(StringBuffer sb, char c) {
151.2628 +        /*
151.2629 +        ByteBuffer bb = null;
151.2630 +        try {
151.2631 +            bb = ThreadLocalCoders.encoderFor("UTF-8")
151.2632 +                .encode(CharBuffer.wrap("" + c));
151.2633 +        } catch (CharacterCodingException x) {
151.2634 +            assert false;
151.2635 +        }
151.2636 +        while (bb.hasRemaining()) {
151.2637 +            int b = bb.get() & 0xff;
151.2638 +            if (b >= 0x80)
151.2639 +                appendEscape(sb, (byte)b);
151.2640 +            else
151.2641 +                sb.append((char)b);
151.2642 +        }
151.2643 +        */
151.2644 +    }
151.2645 +
151.2646 +    // Quote any characters in s that are not permitted
151.2647 +    // by the given mask pair
151.2648 +    //
151.2649 +    private static String quote(String s, long lowMask, long highMask) {
151.2650 +        int n = s.length();
151.2651 +        StringBuffer sb = null;
151.2652 +        boolean allowNonASCII = ((lowMask & L_ESCAPED) != 0);
151.2653 +        for (int i = 0; i < s.length(); i++) {
151.2654 +            char c = s.charAt(i);
151.2655 +            if (c < '\u0080') {
151.2656 +                if (!match(c, lowMask, highMask)) {
151.2657 +                    if (sb == null) {
151.2658 +                        sb = new StringBuffer();
151.2659 +                        sb.append(s.substring(0, i));
151.2660 +                    }
151.2661 +                    appendEscape(sb, (byte)c);
151.2662 +                } else {
151.2663 +                    if (sb != null)
151.2664 +                        sb.append(c);
151.2665 +                }
151.2666 +            } else if (allowNonASCII
151.2667 +                       && (Character.isSpaceChar(c)
151.2668 +                           || Character.isISOControl(c))) {
151.2669 +                if (sb == null) {
151.2670 +                    sb = new StringBuffer();
151.2671 +                    sb.append(s.substring(0, i));
151.2672 +                }
151.2673 +                appendEncoded(sb, c);
151.2674 +            } else {
151.2675 +                if (sb != null)
151.2676 +                    sb.append(c);
151.2677 +            }
151.2678 +        }
151.2679 +        return (sb == null) ? s : sb.toString();
151.2680 +    }
151.2681 +
151.2682 +    // Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets,
151.2683 +    // assuming that s is otherwise legal
151.2684 +    //
151.2685 +    private static String encode(String s) {
151.2686 +        int n = s.length();
151.2687 +        if (n == 0)
151.2688 +            return s;
151.2689 +
151.2690 +        // First check whether we actually need to encode
151.2691 +        for (int i = 0;;) {
151.2692 +            if (s.charAt(i) >= '\u0080')
151.2693 +                break;
151.2694 +            if (++i >= n)
151.2695 +                return s;
151.2696 +        }
151.2697 +/*
151.2698 +        String ns = Normalizer.normalize(s, Normalizer.Form.NFC);
151.2699 +        ByteBuffer bb = null;
151.2700 +        try {
151.2701 +            bb = ThreadLocalCoders.encoderFor("UTF-8")
151.2702 +                .encode(CharBuffer.wrap(ns));
151.2703 +        } catch (CharacterCodingException x) {
151.2704 +            assert false;
151.2705 +        }
151.2706 +*/
151.2707 +        StringBuffer sb = new StringBuffer();
151.2708 +        /*
151.2709 +        while (bb.hasRemaining()) {
151.2710 +            int b = bb.get() & 0xff;
151.2711 +            if (b >= 0x80)
151.2712 +                appendEscape(sb, (byte)b);
151.2713 +            else
151.2714 +                sb.append((char)b);
151.2715 +        }
151.2716 +        */
151.2717 +        return sb.toString();
151.2718 +    }
151.2719 +
151.2720 +    private static int decode(char c) {
151.2721 +        if ((c >= '0') && (c <= '9'))
151.2722 +            return c - '0';
151.2723 +        if ((c >= 'a') && (c <= 'f'))
151.2724 +            return c - 'a' + 10;
151.2725 +        if ((c >= 'A') && (c <= 'F'))
151.2726 +            return c - 'A' + 10;
151.2727 +        assert false;
151.2728 +        return -1;
151.2729 +    }
151.2730 +
151.2731 +    private static byte decode(char c1, char c2) {
151.2732 +        return (byte)(  ((decode(c1) & 0xf) << 4)
151.2733 +                      | ((decode(c2) & 0xf) << 0));
151.2734 +    }
151.2735 +
151.2736 +    // Evaluates all escapes in s, applying UTF-8 decoding if needed.  Assumes
151.2737 +    // that escapes are well-formed syntactically, i.e., of the form %XX.  If a
151.2738 +    // sequence of escaped octets is not valid UTF-8 then the erroneous octets
151.2739 +    // are replaced with '\uFFFD'.
151.2740 +    // Exception: any "%" found between "[]" is left alone. It is an IPv6 literal
151.2741 +    //            with a scope_id
151.2742 +    //
151.2743 +    private static String decode(String s) {
151.2744 +        if (s == null)
151.2745 +            return s;
151.2746 +        int n = s.length();
151.2747 +        if (n == 0)
151.2748 +            return s;
151.2749 +        if (s.indexOf('%') < 0)
151.2750 +            return s;
151.2751 +
151.2752 +        StringBuffer sb = new StringBuffer(n);
151.2753 +        /*
151.2754 +        ByteBuffer bb = ByteBuffer.allocate(n);
151.2755 +        CharBuffer cb = CharBuffer.allocate(n);
151.2756 +        CharsetDecoder dec = ThreadLocalCoders.decoderFor("UTF-8")
151.2757 +            .onMalformedInput(CodingErrorAction.REPLACE)
151.2758 +            .onUnmappableCharacter(CodingErrorAction.REPLACE);
151.2759 +
151.2760 +        // This is not horribly efficient, but it will do for now
151.2761 +        char c = s.charAt(0);
151.2762 +        boolean betweenBrackets = false;
151.2763 +
151.2764 +        for (int i = 0; i < n;) {
151.2765 +            assert c == s.charAt(i);    // Loop invariant
151.2766 +            if (c == '[') {
151.2767 +                betweenBrackets = true;
151.2768 +            } else if (betweenBrackets && c == ']') {
151.2769 +                betweenBrackets = false;
151.2770 +            }
151.2771 +            if (c != '%' || betweenBrackets) {
151.2772 +                sb.append(c);
151.2773 +                if (++i >= n)
151.2774 +                    break;
151.2775 +                c = s.charAt(i);
151.2776 +                continue;
151.2777 +            }
151.2778 +            bb.clear();
151.2779 +            int ui = i;
151.2780 +            for (;;) {
151.2781 +                assert (n - i >= 2);
151.2782 +                bb.put(decode(s.charAt(++i), s.charAt(++i)));
151.2783 +                if (++i >= n)
151.2784 +                    break;
151.2785 +                c = s.charAt(i);
151.2786 +                if (c != '%')
151.2787 +                    break;
151.2788 +            }
151.2789 +            bb.flip();
151.2790 +            cb.clear();
151.2791 +            dec.reset();
151.2792 +            CoderResult cr = dec.decode(bb, cb, true);
151.2793 +            assert cr.isUnderflow();
151.2794 +            cr = dec.flush(cb);
151.2795 +            assert cr.isUnderflow();
151.2796 +            sb.append(cb.flip().toString());
151.2797 +        }
151.2798 +*/
151.2799 +        return sb.toString();
151.2800 +    }
151.2801 +
151.2802 +
151.2803 +    // -- Parsing --
151.2804 +
151.2805 +    // For convenience we wrap the input URI string in a new instance of the
151.2806 +    // following internal class.  This saves always having to pass the input
151.2807 +    // string as an argument to each internal scan/parse method.
151.2808 +
151.2809 +    private class Parser {
151.2810 +
151.2811 +        private String input;           // URI input string
151.2812 +        private boolean requireServerAuthority = false;
151.2813 +
151.2814 +        Parser(String s) {
151.2815 +            input = s;
151.2816 +            string = s;
151.2817 +        }
151.2818 +
151.2819 +        // -- Methods for throwing URISyntaxException in various ways --
151.2820 +
151.2821 +        private void fail(String reason) throws URISyntaxException {
151.2822 +            throw new URISyntaxException(input, reason);
151.2823 +        }
151.2824 +
151.2825 +        private void fail(String reason, int p) throws URISyntaxException {
151.2826 +            throw new URISyntaxException(input, reason, p);
151.2827 +        }
151.2828 +
151.2829 +        private void failExpecting(String expected, int p)
151.2830 +            throws URISyntaxException
151.2831 +        {
151.2832 +            fail("Expected " + expected, p);
151.2833 +        }
151.2834 +
151.2835 +        private void failExpecting(String expected, String prior, int p)
151.2836 +            throws URISyntaxException
151.2837 +        {
151.2838 +            fail("Expected " + expected + " following " + prior, p);
151.2839 +        }
151.2840 +
151.2841 +
151.2842 +        // -- Simple access to the input string --
151.2843 +
151.2844 +        // Return a substring of the input string
151.2845 +        //
151.2846 +        private String substring(int start, int end) {
151.2847 +            return input.substring(start, end);
151.2848 +        }
151.2849 +
151.2850 +        // Return the char at position p,
151.2851 +        // assuming that p < input.length()
151.2852 +        //
151.2853 +        private char charAt(int p) {
151.2854 +            return input.charAt(p);
151.2855 +        }
151.2856 +
151.2857 +        // Tells whether start < end and, if so, whether charAt(start) == c
151.2858 +        //
151.2859 +        private boolean at(int start, int end, char c) {
151.2860 +            return (start < end) && (charAt(start) == c);
151.2861 +        }
151.2862 +
151.2863 +        // Tells whether start + s.length() < end and, if so,
151.2864 +        // whether the chars at the start position match s exactly
151.2865 +        //
151.2866 +        private boolean at(int start, int end, String s) {
151.2867 +            int p = start;
151.2868 +            int sn = s.length();
151.2869 +            if (sn > end - p)
151.2870 +                return false;
151.2871 +            int i = 0;
151.2872 +            while (i < sn) {
151.2873 +                if (charAt(p++) != s.charAt(i)) {
151.2874 +                    break;
151.2875 +                }
151.2876 +                i++;
151.2877 +            }
151.2878 +            return (i == sn);
151.2879 +        }
151.2880 +
151.2881 +
151.2882 +        // -- Scanning --
151.2883 +
151.2884 +        // The various scan and parse methods that follow use a uniform
151.2885 +        // convention of taking the current start position and end index as
151.2886 +        // their first two arguments.  The start is inclusive while the end is
151.2887 +        // exclusive, just as in the String class, i.e., a start/end pair
151.2888 +        // denotes the left-open interval [start, end) of the input string.
151.2889 +        //
151.2890 +        // These methods never proceed past the end position.  They may return
151.2891 +        // -1 to indicate outright failure, but more often they simply return
151.2892 +        // the position of the first char after the last char scanned.  Thus
151.2893 +        // a typical idiom is
151.2894 +        //
151.2895 +        //     int p = start;
151.2896 +        //     int q = scan(p, end, ...);
151.2897 +        //     if (q > p)
151.2898 +        //         // We scanned something
151.2899 +        //         ...;
151.2900 +        //     else if (q == p)
151.2901 +        //         // We scanned nothing
151.2902 +        //         ...;
151.2903 +        //     else if (q == -1)
151.2904 +        //         // Something went wrong
151.2905 +        //         ...;
151.2906 +
151.2907 +
151.2908 +        // Scan a specific char: If the char at the given start position is
151.2909 +        // equal to c, return the index of the next char; otherwise, return the
151.2910 +        // start position.
151.2911 +        //
151.2912 +        private int scan(int start, int end, char c) {
151.2913 +            if ((start < end) && (charAt(start) == c))
151.2914 +                return start + 1;
151.2915 +            return start;
151.2916 +        }
151.2917 +
151.2918 +        // Scan forward from the given start position.  Stop at the first char
151.2919 +        // in the err string (in which case -1 is returned), or the first char
151.2920 +        // in the stop string (in which case the index of the preceding char is
151.2921 +        // returned), or the end of the input string (in which case the length
151.2922 +        // of the input string is returned).  May return the start position if
151.2923 +        // nothing matches.
151.2924 +        //
151.2925 +        private int scan(int start, int end, String err, String stop) {
151.2926 +            int p = start;
151.2927 +            while (p < end) {
151.2928 +                char c = charAt(p);
151.2929 +                if (err.indexOf(c) >= 0)
151.2930 +                    return -1;
151.2931 +                if (stop.indexOf(c) >= 0)
151.2932 +                    break;
151.2933 +                p++;
151.2934 +            }
151.2935 +            return p;
151.2936 +        }
151.2937 +
151.2938 +        // Scan a potential escape sequence, starting at the given position,
151.2939 +        // with the given first char (i.e., charAt(start) == c).
151.2940 +        //
151.2941 +        // This method assumes that if escapes are allowed then visible
151.2942 +        // non-US-ASCII chars are also allowed.
151.2943 +        //
151.2944 +        private int scanEscape(int start, int n, char first)
151.2945 +            throws URISyntaxException
151.2946 +        {
151.2947 +            int p = start;
151.2948 +            char c = first;
151.2949 +            if (c == '%') {
151.2950 +                // Process escape pair
151.2951 +                if ((p + 3 <= n)
151.2952 +                    && match(charAt(p + 1), L_HEX, H_HEX)
151.2953 +                    && match(charAt(p + 2), L_HEX, H_HEX)) {
151.2954 +                    return p + 3;
151.2955 +                }
151.2956 +                fail("Malformed escape pair", p);
151.2957 +            } else if ((c > 128)
151.2958 +                       && !Character.isSpaceChar(c)
151.2959 +                       && !Character.isISOControl(c)) {
151.2960 +                // Allow unescaped but visible non-US-ASCII chars
151.2961 +                return p + 1;
151.2962 +            }
151.2963 +            return p;
151.2964 +        }
151.2965 +
151.2966 +        // Scan chars that match the given mask pair
151.2967 +        //
151.2968 +        private int scan(int start, int n, long lowMask, long highMask)
151.2969 +            throws URISyntaxException
151.2970 +        {
151.2971 +            int p = start;
151.2972 +            while (p < n) {
151.2973 +                char c = charAt(p);
151.2974 +                if (match(c, lowMask, highMask)) {
151.2975 +                    p++;
151.2976 +                    continue;
151.2977 +                }
151.2978 +                if ((lowMask & L_ESCAPED) != 0) {
151.2979 +                    int q = scanEscape(p, n, c);
151.2980 +                    if (q > p) {
151.2981 +                        p = q;
151.2982 +                        continue;
151.2983 +                    }
151.2984 +                }
151.2985 +                break;
151.2986 +            }
151.2987 +            return p;
151.2988 +        }
151.2989 +
151.2990 +        // Check that each of the chars in [start, end) matches the given mask
151.2991 +        //
151.2992 +        private void checkChars(int start, int end,
151.2993 +                                long lowMask, long highMask,
151.2994 +                                String what)
151.2995 +            throws URISyntaxException
151.2996 +        {
151.2997 +            int p = scan(start, end, lowMask, highMask);
151.2998 +            if (p < end)
151.2999 +                fail("Illegal character in " + what, p);
151.3000 +        }
151.3001 +
151.3002 +        // Check that the char at position p matches the given mask
151.3003 +        //
151.3004 +        private void checkChar(int p,
151.3005 +                               long lowMask, long highMask,
151.3006 +                               String what)
151.3007 +            throws URISyntaxException
151.3008 +        {
151.3009 +            checkChars(p, p + 1, lowMask, highMask, what);
151.3010 +        }
151.3011 +
151.3012 +
151.3013 +        // -- Parsing --
151.3014 +
151.3015 +        // [<scheme>:]<scheme-specific-part>[#<fragment>]
151.3016 +        //
151.3017 +        void parse(boolean rsa) throws URISyntaxException {
151.3018 +            requireServerAuthority = rsa;
151.3019 +            int ssp;                    // Start of scheme-specific part
151.3020 +            int n = input.length();
151.3021 +            int p = scan(0, n, "/?#", ":");
151.3022 +            if ((p >= 0) && at(p, n, ':')) {
151.3023 +                if (p == 0)
151.3024 +                    failExpecting("scheme name", 0);
151.3025 +                checkChar(0, L_ALPHA, H_ALPHA, "scheme name");
151.3026 +                checkChars(1, p, L_SCHEME, H_SCHEME, "scheme name");
151.3027 +                scheme = substring(0, p);
151.3028 +                p++;                    // Skip ':'
151.3029 +                ssp = p;
151.3030 +                if (at(p, n, '/')) {
151.3031 +                    p = parseHierarchical(p, n);
151.3032 +                } else {
151.3033 +                    int q = scan(p, n, "", "#");
151.3034 +                    if (q <= p)
151.3035 +                        failExpecting("scheme-specific part", p);
151.3036 +                    checkChars(p, q, L_URIC, H_URIC, "opaque part");
151.3037 +                    p = q;
151.3038 +                }
151.3039 +            } else {
151.3040 +                ssp = 0;
151.3041 +                p = parseHierarchical(0, n);
151.3042 +            }
151.3043 +            schemeSpecificPart = substring(ssp, p);
151.3044 +            if (at(p, n, '#')) {
151.3045 +                checkChars(p + 1, n, L_URIC, H_URIC, "fragment");
151.3046 +                fragment = substring(p + 1, n);
151.3047 +                p = n;
151.3048 +            }
151.3049 +            if (p < n)
151.3050 +                fail("end of URI", p);
151.3051 +        }
151.3052 +
151.3053 +        // [//authority]<path>[?<query>]
151.3054 +        //
151.3055 +        // DEVIATION from RFC2396: We allow an empty authority component as
151.3056 +        // long as it's followed by a non-empty path, query component, or
151.3057 +        // fragment component.  This is so that URIs such as "file:///foo/bar"
151.3058 +        // will parse.  This seems to be the intent of RFC2396, though the
151.3059 +        // grammar does not permit it.  If the authority is empty then the
151.3060 +        // userInfo, host, and port components are undefined.
151.3061 +        //
151.3062 +        // DEVIATION from RFC2396: We allow empty relative paths.  This seems
151.3063 +        // to be the intent of RFC2396, but the grammar does not permit it.
151.3064 +        // The primary consequence of this deviation is that "#f" parses as a
151.3065 +        // relative URI with an empty path.
151.3066 +        //
151.3067 +        private int parseHierarchical(int start, int n)
151.3068 +            throws URISyntaxException
151.3069 +        {
151.3070 +            int p = start;
151.3071 +            if (at(p, n, '/') && at(p + 1, n, '/')) {
151.3072 +                p += 2;
151.3073 +                int q = scan(p, n, "", "/?#");
151.3074 +                if (q > p) {
151.3075 +                    p = parseAuthority(p, q);
151.3076 +                } else if (q < n) {
151.3077 +                    // DEVIATION: Allow empty authority prior to non-empty
151.3078 +                    // path, query component or fragment identifier
151.3079 +                } else
151.3080 +                    failExpecting("authority", p);
151.3081 +            }
151.3082 +            int q = scan(p, n, "", "?#"); // DEVIATION: May be empty
151.3083 +            checkChars(p, q, L_PATH, H_PATH, "path");
151.3084 +            path = substring(p, q);
151.3085 +            p = q;
151.3086 +            if (at(p, n, '?')) {
151.3087 +                p++;
151.3088 +                q = scan(p, n, "", "#");
151.3089 +                checkChars(p, q, L_URIC, H_URIC, "query");
151.3090 +                query = substring(p, q);
151.3091 +                p = q;
151.3092 +            }
151.3093 +            return p;
151.3094 +        }
151.3095 +
151.3096 +        // authority     = server | reg_name
151.3097 +        //
151.3098 +        // Ambiguity: An authority that is a registry name rather than a server
151.3099 +        // might have a prefix that parses as a server.  We use the fact that
151.3100 +        // the authority component is always followed by '/' or the end of the
151.3101 +        // input string to resolve this: If the complete authority did not
151.3102 +        // parse as a server then we try to parse it as a registry name.
151.3103 +        //
151.3104 +        private int parseAuthority(int start, int n)
151.3105 +            throws URISyntaxException
151.3106 +        {
151.3107 +            int p = start;
151.3108 +            int q = p;
151.3109 +            URISyntaxException ex = null;
151.3110 +
151.3111 +            boolean serverChars;
151.3112 +            boolean regChars;
151.3113 +
151.3114 +            if (scan(p, n, "", "]") > p) {
151.3115 +                // contains a literal IPv6 address, therefore % is allowed
151.3116 +                serverChars = (scan(p, n, L_SERVER_PERCENT, H_SERVER_PERCENT) == n);
151.3117 +            } else {
151.3118 +                serverChars = (scan(p, n, L_SERVER, H_SERVER) == n);
151.3119 +            }
151.3120 +            regChars = (scan(p, n, L_REG_NAME, H_REG_NAME) == n);
151.3121 +
151.3122 +            if (regChars && !serverChars) {
151.3123 +                // Must be a registry-based authority
151.3124 +                authority = substring(p, n);
151.3125 +                return n;
151.3126 +            }
151.3127 +
151.3128 +            if (serverChars) {
151.3129 +                // Might be (probably is) a server-based authority, so attempt
151.3130 +                // to parse it as such.  If the attempt fails, try to treat it
151.3131 +                // as a registry-based authority.
151.3132 +                try {
151.3133 +                    q = parseServer(p, n);
151.3134 +                    if (q < n)
151.3135 +                        failExpecting("end of authority", q);
151.3136 +                    authority = substring(p, n);
151.3137 +                } catch (URISyntaxException x) {
151.3138 +                    // Undo results of failed parse
151.3139 +                    userInfo = null;
151.3140 +                    host = null;
151.3141 +                    port = -1;
151.3142 +                    if (requireServerAuthority) {
151.3143 +                        // If we're insisting upon a server-based authority,
151.3144 +                        // then just re-throw the exception
151.3145 +                        throw x;
151.3146 +                    } else {
151.3147 +                        // Save the exception in case it doesn't parse as a
151.3148 +                        // registry either
151.3149 +                        ex = x;
151.3150 +                        q = p;
151.3151 +                    }
151.3152 +                }
151.3153 +            }
151.3154 +
151.3155 +            if (q < n) {
151.3156 +                if (regChars) {
151.3157 +                    // Registry-based authority
151.3158 +                    authority = substring(p, n);
151.3159 +                } else if (ex != null) {
151.3160 +                    // Re-throw exception; it was probably due to
151.3161 +                    // a malformed IPv6 address
151.3162 +                    throw ex;
151.3163 +                } else {
151.3164 +                    fail("Illegal character in authority", q);
151.3165 +                }
151.3166 +            }
151.3167 +
151.3168 +            return n;
151.3169 +        }
151.3170 +
151.3171 +
151.3172 +        // [<userinfo>@]<host>[:<port>]
151.3173 +        //
151.3174 +        private int parseServer(int start, int n)
151.3175 +            throws URISyntaxException
151.3176 +        {
151.3177 +            int p = start;
151.3178 +            int q;
151.3179 +
151.3180 +            // userinfo
151.3181 +            q = scan(p, n, "/?#", "@");
151.3182 +            if ((q >= p) && at(q, n, '@')) {
151.3183 +                checkChars(p, q, L_USERINFO, H_USERINFO, "user info");
151.3184 +                userInfo = substring(p, q);
151.3185 +                p = q + 1;              // Skip '@'
151.3186 +            }
151.3187 +
151.3188 +            // hostname, IPv4 address, or IPv6 address
151.3189 +            if (at(p, n, '[')) {
151.3190 +                // DEVIATION from RFC2396: Support IPv6 addresses, per RFC2732
151.3191 +                p++;
151.3192 +                q = scan(p, n, "/?#", "]");
151.3193 +                if ((q > p) && at(q, n, ']')) {
151.3194 +                    // look for a "%" scope id
151.3195 +                    int r = scan (p, q, "", "%");
151.3196 +                    if (r > p) {
151.3197 +                        parseIPv6Reference(p, r);
151.3198 +                        if (r+1 == q) {
151.3199 +                            fail ("scope id expected");
151.3200 +                        }
151.3201 +                        checkChars (r+1, q, L_ALPHANUM, H_ALPHANUM,
151.3202 +                                                "scope id");
151.3203 +                    } else {
151.3204 +                        parseIPv6Reference(p, q);
151.3205 +                    }
151.3206 +                    host = substring(p-1, q+1);
151.3207 +                    p = q + 1;
151.3208 +                } else {
151.3209 +                    failExpecting("closing bracket for IPv6 address", q);
151.3210 +                }
151.3211 +            } else {
151.3212 +                q = parseIPv4Address(p, n);
151.3213 +                if (q <= p)
151.3214 +                    q = parseHostname(p, n);
151.3215 +                p = q;
151.3216 +            }
151.3217 +
151.3218 +            // port
151.3219 +            if (at(p, n, ':')) {
151.3220 +                p++;
151.3221 +                q = scan(p, n, "", "/");
151.3222 +                if (q > p) {
151.3223 +                    checkChars(p, q, L_DIGIT, H_DIGIT, "port number");
151.3224 +                    try {
151.3225 +                        port = Integer.parseInt(substring(p, q));
151.3226 +                    } catch (NumberFormatException x) {
151.3227 +                        fail("Malformed port number", p);
151.3228 +                    }
151.3229 +                    p = q;
151.3230 +                }
151.3231 +            }
151.3232 +            if (p < n)
151.3233 +                failExpecting("port number", p);
151.3234 +
151.3235 +            return p;
151.3236 +        }
151.3237 +
151.3238 +        // Scan a string of decimal digits whose value fits in a byte
151.3239 +        //
151.3240 +        private int scanByte(int start, int n)
151.3241 +            throws URISyntaxException
151.3242 +        {
151.3243 +            int p = start;
151.3244 +            int q = scan(p, n, L_DIGIT, H_DIGIT);
151.3245 +            if (q <= p) return q;
151.3246 +            if (Integer.parseInt(substring(p, q)) > 255) return p;
151.3247 +            return q;
151.3248 +        }
151.3249 +
151.3250 +        // Scan an IPv4 address.
151.3251 +        //
151.3252 +        // If the strict argument is true then we require that the given
151.3253 +        // interval contain nothing besides an IPv4 address; if it is false
151.3254 +        // then we only require that it start with an IPv4 address.
151.3255 +        //
151.3256 +        // If the interval does not contain or start with (depending upon the
151.3257 +        // strict argument) a legal IPv4 address characters then we return -1
151.3258 +        // immediately; otherwise we insist that these characters parse as a
151.3259 +        // legal IPv4 address and throw an exception on failure.
151.3260 +        //
151.3261 +        // We assume that any string of decimal digits and dots must be an IPv4
151.3262 +        // address.  It won't parse as a hostname anyway, so making that
151.3263 +        // assumption here allows more meaningful exceptions to be thrown.
151.3264 +        //
151.3265 +        private int scanIPv4Address(int start, int n, boolean strict)
151.3266 +            throws URISyntaxException
151.3267 +        {
151.3268 +            int p = start;
151.3269 +            int q;
151.3270 +            int m = scan(p, n, L_DIGIT | L_DOT, H_DIGIT | H_DOT);
151.3271 +            if ((m <= p) || (strict && (m != n)))
151.3272 +                return -1;
151.3273 +            for (;;) {
151.3274 +                // Per RFC2732: At most three digits per byte
151.3275 +                // Further constraint: Each element fits in a byte
151.3276 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
151.3277 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
151.3278 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
151.3279 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
151.3280 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
151.3281 +                if ((q = scan(p, m, '.')) <= p) break;  p = q;
151.3282 +                if ((q = scanByte(p, m)) <= p) break;   p = q;
151.3283 +                if (q < m) break;
151.3284 +                return q;
151.3285 +            }
151.3286 +            fail("Malformed IPv4 address", q);
151.3287 +            return -1;
151.3288 +        }
151.3289 +
151.3290 +        // Take an IPv4 address: Throw an exception if the given interval
151.3291 +        // contains anything except an IPv4 address
151.3292 +        //
151.3293 +        private int takeIPv4Address(int start, int n, String expected)
151.3294 +            throws URISyntaxException
151.3295 +        {
151.3296 +            int p = scanIPv4Address(start, n, true);
151.3297 +            if (p <= start)
151.3298 +                failExpecting(expected, start);
151.3299 +            return p;
151.3300 +        }
151.3301 +
151.3302 +        // Attempt to parse an IPv4 address, returning -1 on failure but
151.3303 +        // allowing the given interval to contain [:<characters>] after
151.3304 +        // the IPv4 address.
151.3305 +        //
151.3306 +        private int parseIPv4Address(int start, int n) {
151.3307 +            int p;
151.3308 +
151.3309 +            try {
151.3310 +                p = scanIPv4Address(start, n, false);
151.3311 +            } catch (URISyntaxException x) {
151.3312 +                return -1;
151.3313 +            } catch (NumberFormatException nfe) {
151.3314 +                return -1;
151.3315 +            }
151.3316 +
151.3317 +            if (p > start && p < n) {
151.3318 +                // IPv4 address is followed by something - check that
151.3319 +                // it's a ":" as this is the only valid character to
151.3320 +                // follow an address.
151.3321 +                if (charAt(p) != ':') {
151.3322 +                    p = -1;
151.3323 +                }
151.3324 +            }
151.3325 +
151.3326 +            if (p > start)
151.3327 +                host = substring(start, p);
151.3328 +
151.3329 +            return p;
151.3330 +        }
151.3331 +
151.3332 +        // hostname      = domainlabel [ "." ] | 1*( domainlabel "." ) toplabel [ "." ]
151.3333 +        // domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
151.3334 +        // toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
151.3335 +        //
151.3336 +        private int parseHostname(int start, int n)
151.3337 +            throws URISyntaxException
151.3338 +        {
151.3339 +            int p = start;
151.3340 +            int q;
151.3341 +            int l = -1;                 // Start of last parsed label
151.3342 +
151.3343 +            do {
151.3344 +                // domainlabel = alphanum [ *( alphanum | "-" ) alphanum ]
151.3345 +                q = scan(p, n, L_ALPHANUM, H_ALPHANUM);
151.3346 +                if (q <= p)
151.3347 +                    break;
151.3348 +                l = p;
151.3349 +                if (q > p) {
151.3350 +                    p = q;
151.3351 +                    q = scan(p, n, L_ALPHANUM | L_DASH, H_ALPHANUM | H_DASH);
151.3352 +                    if (q > p) {
151.3353 +                        if (charAt(q - 1) == '-')
151.3354 +                            fail("Illegal character in hostname", q - 1);
151.3355 +                        p = q;
151.3356 +                    }
151.3357 +                }
151.3358 +                q = scan(p, n, '.');
151.3359 +                if (q <= p)
151.3360 +                    break;
151.3361 +                p = q;
151.3362 +            } while (p < n);
151.3363 +
151.3364 +            if ((p < n) && !at(p, n, ':'))
151.3365 +                fail("Illegal character in hostname", p);
151.3366 +
151.3367 +            if (l < 0)
151.3368 +                failExpecting("hostname", start);
151.3369 +
151.3370 +            // for a fully qualified hostname check that the rightmost
151.3371 +            // label starts with an alpha character.
151.3372 +            if (l > start && !match(charAt(l), L_ALPHA, H_ALPHA)) {
151.3373 +                fail("Illegal character in hostname", l);
151.3374 +            }
151.3375 +
151.3376 +            host = substring(start, p);
151.3377 +            return p;
151.3378 +        }
151.3379 +
151.3380 +
151.3381 +        // IPv6 address parsing, from RFC2373: IPv6 Addressing Architecture
151.3382 +        //
151.3383 +        // Bug: The grammar in RFC2373 Appendix B does not allow addresses of
151.3384 +        // the form ::12.34.56.78, which are clearly shown in the examples
151.3385 +        // earlier in the document.  Here is the original grammar:
151.3386 +        //
151.3387 +        //   IPv6address = hexpart [ ":" IPv4address ]
151.3388 +        //   hexpart     = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ]
151.3389 +        //   hexseq      = hex4 *( ":" hex4)
151.3390 +        //   hex4        = 1*4HEXDIG
151.3391 +        //
151.3392 +        // We therefore use the following revised grammar:
151.3393 +        //
151.3394 +        //   IPv6address = hexseq [ ":" IPv4address ]
151.3395 +        //                 | hexseq [ "::" [ hexpost ] ]
151.3396 +        //                 | "::" [ hexpost ]
151.3397 +        //   hexpost     = hexseq | hexseq ":" IPv4address | IPv4address
151.3398 +        //   hexseq      = hex4 *( ":" hex4)
151.3399 +        //   hex4        = 1*4HEXDIG
151.3400 +        //
151.3401 +        // This covers all and only the following cases:
151.3402 +        //
151.3403 +        //   hexseq
151.3404 +        //   hexseq : IPv4address
151.3405 +        //   hexseq ::
151.3406 +        //   hexseq :: hexseq
151.3407 +        //   hexseq :: hexseq : IPv4address
151.3408 +        //   hexseq :: IPv4address
151.3409 +        //   :: hexseq
151.3410 +        //   :: hexseq : IPv4address
151.3411 +        //   :: IPv4address
151.3412 +        //   ::
151.3413 +        //
151.3414 +        // Additionally we constrain the IPv6 address as follows :-
151.3415 +        //
151.3416 +        //  i.  IPv6 addresses without compressed zeros should contain
151.3417 +        //      exactly 16 bytes.
151.3418 +        //
151.3419 +        //  ii. IPv6 addresses with compressed zeros should contain
151.3420 +        //      less than 16 bytes.
151.3421 +
151.3422 +        private int ipv6byteCount = 0;
151.3423 +
151.3424 +        private int parseIPv6Reference(int start, int n)
151.3425 +            throws URISyntaxException
151.3426 +        {
151.3427 +            int p = start;
151.3428 +            int q;
151.3429 +            boolean compressedZeros = false;
151.3430 +
151.3431 +            q = scanHexSeq(p, n);
151.3432 +
151.3433 +            if (q > p) {
151.3434 +                p = q;
151.3435 +                if (at(p, n, "::")) {
151.3436 +                    compressedZeros = true;
151.3437 +                    p = scanHexPost(p + 2, n);
151.3438 +                } else if (at(p, n, ':')) {
151.3439 +                    p = takeIPv4Address(p + 1,  n, "IPv4 address");
151.3440 +                    ipv6byteCount += 4;
151.3441 +                }
151.3442 +            } else if (at(p, n, "::")) {
151.3443 +                compressedZeros = true;
151.3444 +                p = scanHexPost(p + 2, n);
151.3445 +            }
151.3446 +            if (p < n)
151.3447 +                fail("Malformed IPv6 address", start);
151.3448 +            if (ipv6byteCount > 16)
151.3449 +                fail("IPv6 address too long", start);
151.3450 +            if (!compressedZeros && ipv6byteCount < 16)
151.3451 +                fail("IPv6 address too short", start);
151.3452 +            if (compressedZeros && ipv6byteCount == 16)
151.3453 +                fail("Malformed IPv6 address", start);
151.3454 +
151.3455 +            return p;
151.3456 +        }
151.3457 +
151.3458 +        private int scanHexPost(int start, int n)
151.3459 +            throws URISyntaxException
151.3460 +        {
151.3461 +            int p = start;
151.3462 +            int q;
151.3463 +
151.3464 +            if (p == n)
151.3465 +                return p;
151.3466 +
151.3467 +            q = scanHexSeq(p, n);
151.3468 +            if (q > p) {
151.3469 +                p = q;
151.3470 +                if (at(p, n, ':')) {
151.3471 +                    p++;
151.3472 +                    p = takeIPv4Address(p, n, "hex digits or IPv4 address");
151.3473 +                    ipv6byteCount += 4;
151.3474 +                }
151.3475 +            } else {
151.3476 +                p = takeIPv4Address(p, n, "hex digits or IPv4 address");
151.3477 +                ipv6byteCount += 4;
151.3478 +            }
151.3479 +            return p;
151.3480 +        }
151.3481 +
151.3482 +        // Scan a hex sequence; return -1 if one could not be scanned
151.3483 +        //
151.3484 +        private int scanHexSeq(int start, int n)
151.3485 +            throws URISyntaxException
151.3486 +        {
151.3487 +            int p = start;
151.3488 +            int q;
151.3489 +
151.3490 +            q = scan(p, n, L_HEX, H_HEX);
151.3491 +            if (q <= p)
151.3492 +                return -1;
151.3493 +            if (at(q, n, '.'))          // Beginning of IPv4 address
151.3494 +                return -1;
151.3495 +            if (q > p + 4)
151.3496 +                fail("IPv6 hexadecimal digit sequence too long", p);
151.3497 +            ipv6byteCount += 2;
151.3498 +            p = q;
151.3499 +            while (p < n) {
151.3500 +                if (!at(p, n, ':'))
151.3501 +                    break;
151.3502 +                if (at(p + 1, n, ':'))
151.3503 +                    break;              // "::"
151.3504 +                p++;
151.3505 +                q = scan(p, n, L_HEX, H_HEX);
151.3506 +                if (q <= p)
151.3507 +                    failExpecting("digits for an IPv6 address", p);
151.3508 +                if (at(q, n, '.')) {    // Beginning of IPv4 address
151.3509 +                    p--;
151.3510 +                    break;
151.3511 +                }
151.3512 +                if (q > p + 4)
151.3513 +                    fail("IPv6 hexadecimal digit sequence too long", p);
151.3514 +                ipv6byteCount += 2;
151.3515 +                p = q;
151.3516 +            }
151.3517 +
151.3518 +            return p;
151.3519 +        }
151.3520 +
151.3521 +    }
151.3522 +
151.3523 +}
   152.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   152.2 +++ b/rt/emul/compact/src/main/java/java/net/URISyntaxException.java	Mon Oct 07 14:20:58 2013 +0200
   152.3 @@ -0,0 +1,135 @@
   152.4 +/*
   152.5 + * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
   152.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   152.7 + *
   152.8 + * This code is free software; you can redistribute it and/or modify it
   152.9 + * under the terms of the GNU General Public License version 2 only, as
  152.10 + * published by the Free Software Foundation.  Oracle designates this
  152.11 + * particular file as subject to the "Classpath" exception as provided
  152.12 + * by Oracle in the LICENSE file that accompanied this code.
  152.13 + *
  152.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  152.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  152.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  152.17 + * version 2 for more details (a copy is included in the LICENSE file that
  152.18 + * accompanied this code).
  152.19 + *
  152.20 + * You should have received a copy of the GNU General Public License version
  152.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  152.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  152.23 + *
  152.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  152.25 + * or visit www.oracle.com if you need additional information or have any
  152.26 + * questions.
  152.27 + */
  152.28 +
  152.29 +package java.net;
  152.30 +
  152.31 +
  152.32 +/**
  152.33 + * Checked exception thrown to indicate that a string could not be parsed as a
  152.34 + * URI reference.
  152.35 + *
  152.36 + * @author Mark Reinhold
  152.37 + * @see URI
  152.38 + * @since 1.4
  152.39 + */
  152.40 +
  152.41 +public class URISyntaxException
  152.42 +    extends Exception
  152.43 +{
  152.44 +    private static final long serialVersionUID = 2137979680897488891L;
  152.45 +
  152.46 +    private String input;
  152.47 +    private int index;
  152.48 +
  152.49 +    /**
  152.50 +     * Constructs an instance from the given input string, reason, and error
  152.51 +     * index.
  152.52 +     *
  152.53 +     * @param  input   The input string
  152.54 +     * @param  reason  A string explaining why the input could not be parsed
  152.55 +     * @param  index   The index at which the parse error occurred,
  152.56 +     *                 or <tt>-1</tt> if the index is not known
  152.57 +     *
  152.58 +     * @throws  NullPointerException
  152.59 +     *          If either the input or reason strings are <tt>null</tt>
  152.60 +     *
  152.61 +     * @throws  IllegalArgumentException
  152.62 +     *          If the error index is less than <tt>-1</tt>
  152.63 +     */
  152.64 +    public URISyntaxException(String input, String reason, int index) {
  152.65 +        super(reason);
  152.66 +        if ((input == null) || (reason == null))
  152.67 +            throw new NullPointerException();
  152.68 +        if (index < -1)
  152.69 +            throw new IllegalArgumentException();
  152.70 +        this.input = input;
  152.71 +        this.index = index;
  152.72 +    }
  152.73 +
  152.74 +    /**
  152.75 +     * Constructs an instance from the given input string and reason.  The
  152.76 +     * resulting object will have an error index of <tt>-1</tt>.
  152.77 +     *
  152.78 +     * @param  input   The input string
  152.79 +     * @param  reason  A string explaining why the input could not be parsed
  152.80 +     *
  152.81 +     * @throws  NullPointerException
  152.82 +     *          If either the input or reason strings are <tt>null</tt>
  152.83 +     */
  152.84 +    public URISyntaxException(String input, String reason) {
  152.85 +        this(input, reason, -1);
  152.86 +    }
  152.87 +
  152.88 +    /**
  152.89 +     * Returns the input string.
  152.90 +     *
  152.91 +     * @return  The input string
  152.92 +     */
  152.93 +    public String getInput() {
  152.94 +        return input;
  152.95 +    }
  152.96 +
  152.97 +    /**
  152.98 +     * Returns a string explaining why the input string could not be parsed.
  152.99 +     *
 152.100 +     * @return  The reason string
 152.101 +     */
 152.102 +    public String getReason() {
 152.103 +        return super.getMessage();
 152.104 +    }
 152.105 +
 152.106 +    /**
 152.107 +     * Returns an index into the input string of the position at which the
 152.108 +     * parse error occurred, or <tt>-1</tt> if this position is not known.
 152.109 +     *
 152.110 +     * @return  The error index
 152.111 +     */
 152.112 +    public int getIndex() {
 152.113 +        return index;
 152.114 +    }
 152.115 +
 152.116 +    /**
 152.117 +     * Returns a string describing the parse error.  The resulting string
 152.118 +     * consists of the reason string followed by a colon character
 152.119 +     * (<tt>':'</tt>), a space, and the input string.  If the error index is
 152.120 +     * defined then the string <tt>" at index "</tt> followed by the index, in
 152.121 +     * decimal, is inserted after the reason string and before the colon
 152.122 +     * character.
 152.123 +     *
 152.124 +     * @return  A string describing the parse error
 152.125 +     */
 152.126 +    public String getMessage() {
 152.127 +        StringBuffer sb = new StringBuffer();
 152.128 +        sb.append(getReason());
 152.129 +        if (index > -1) {
 152.130 +            sb.append(" at index ");
 152.131 +            sb.append(index);
 152.132 +        }
 152.133 +        sb.append(": ");
 152.134 +        sb.append(input);
 152.135 +        return sb.toString();
 152.136 +    }
 152.137 +
 152.138 +}
   153.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   153.2 +++ b/rt/emul/compact/src/main/java/java/util/EnumMap.java	Mon Oct 07 14:20:58 2013 +0200
   153.3 @@ -0,0 +1,797 @@
   153.4 +/*
   153.5 + * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
   153.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   153.7 + *
   153.8 + * This code is free software; you can redistribute it and/or modify it
   153.9 + * under the terms of the GNU General Public License version 2 only, as
  153.10 + * published by the Free Software Foundation.  Oracle designates this
  153.11 + * particular file as subject to the "Classpath" exception as provided
  153.12 + * by Oracle in the LICENSE file that accompanied this code.
  153.13 + *
  153.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  153.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  153.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  153.17 + * version 2 for more details (a copy is included in the LICENSE file that
  153.18 + * accompanied this code).
  153.19 + *
  153.20 + * You should have received a copy of the GNU General Public License version
  153.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  153.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  153.23 + *
  153.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  153.25 + * or visit www.oracle.com if you need additional information or have any
  153.26 + * questions.
  153.27 + */
  153.28 +
  153.29 +package java.util;
  153.30 +
  153.31 +import java.util.Map.Entry;
  153.32 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  153.33 +
  153.34 +/**
  153.35 + * A specialized {@link Map} implementation for use with enum type keys.  All
  153.36 + * of the keys in an enum map must come from a single enum type that is
  153.37 + * specified, explicitly or implicitly, when the map is created.  Enum maps
  153.38 + * are represented internally as arrays.  This representation is extremely
  153.39 + * compact and efficient.
  153.40 + *
  153.41 + * <p>Enum maps are maintained in the <i>natural order</i> of their keys
  153.42 + * (the order in which the enum constants are declared).  This is reflected
  153.43 + * in the iterators returned by the collections views ({@link #keySet()},
  153.44 + * {@link #entrySet()}, and {@link #values()}).
  153.45 + *
  153.46 + * <p>Iterators returned by the collection views are <i>weakly consistent</i>:
  153.47 + * they will never throw {@link ConcurrentModificationException} and they may
  153.48 + * or may not show the effects of any modifications to the map that occur while
  153.49 + * the iteration is in progress.
  153.50 + *
  153.51 + * <p>Null keys are not permitted.  Attempts to insert a null key will
  153.52 + * throw {@link NullPointerException}.  Attempts to test for the
  153.53 + * presence of a null key or to remove one will, however, function properly.
  153.54 + * Null values are permitted.
  153.55 +
  153.56 + * <P>Like most collection implementations <tt>EnumMap</tt> is not
  153.57 + * synchronized. If multiple threads access an enum map concurrently, and at
  153.58 + * least one of the threads modifies the map, it should be synchronized
  153.59 + * externally.  This is typically accomplished by synchronizing on some
  153.60 + * object that naturally encapsulates the enum map.  If no such object exists,
  153.61 + * the map should be "wrapped" using the {@link Collections#synchronizedMap}
  153.62 + * method.  This is best done at creation time, to prevent accidental
  153.63 + * unsynchronized access:
  153.64 + *
  153.65 + * <pre>
  153.66 + *     Map&lt;EnumKey, V&gt; m
  153.67 + *         = Collections.synchronizedMap(new EnumMap&lt;EnumKey, V&gt;(...));
  153.68 + * </pre>
  153.69 + *
  153.70 + * <p>Implementation note: All basic operations execute in constant time.
  153.71 + * They are likely (though not guaranteed) to be faster than their
  153.72 + * {@link HashMap} counterparts.
  153.73 + *
  153.74 + * <p>This class is a member of the
  153.75 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  153.76 + * Java Collections Framework</a>.
  153.77 + *
  153.78 + * @author Josh Bloch
  153.79 + * @see EnumSet
  153.80 + * @since 1.5
  153.81 + */
  153.82 +public class EnumMap<K extends Enum<K>, V> extends AbstractMap<K, V>
  153.83 +    implements java.io.Serializable, Cloneable
  153.84 +{
  153.85 +    /**
  153.86 +     * The <tt>Class</tt> object for the enum type of all the keys of this map.
  153.87 +     *
  153.88 +     * @serial
  153.89 +     */
  153.90 +    private final Class<K> keyType;
  153.91 +
  153.92 +    /**
  153.93 +     * All of the values comprising K.  (Cached for performance.)
  153.94 +     */
  153.95 +    private transient K[] keyUniverse;
  153.96 +
  153.97 +    /**
  153.98 +     * Array representation of this map.  The ith element is the value
  153.99 +     * to which universe[i] is currently mapped, or null if it isn't
 153.100 +     * mapped to anything, or NULL if it's mapped to null.
 153.101 +     */
 153.102 +    private transient Object[] vals;
 153.103 +
 153.104 +    /**
 153.105 +     * The number of mappings in this map.
 153.106 +     */
 153.107 +    private transient int size = 0;
 153.108 +
 153.109 +    /**
 153.110 +     * Distinguished non-null value for representing null values.
 153.111 +     */
 153.112 +    private static final Object NULL = new Integer(0);
 153.113 +
 153.114 +    private Object maskNull(Object value) {
 153.115 +        return (value == null ? NULL : value);
 153.116 +    }
 153.117 +
 153.118 +    private V unmaskNull(Object value) {
 153.119 +        return (V) (value == NULL ? null : value);
 153.120 +    }
 153.121 +
 153.122 +    private static final Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
 153.123 +
 153.124 +    /**
 153.125 +     * Creates an empty enum map with the specified key type.
 153.126 +     *
 153.127 +     * @param keyType the class object of the key type for this enum map
 153.128 +     * @throws NullPointerException if <tt>keyType</tt> is null
 153.129 +     */
 153.130 +    public EnumMap(Class<K> keyType) {
 153.131 +        this.keyType = keyType;
 153.132 +        keyUniverse = getKeyUniverse(keyType);
 153.133 +        vals = new Object[keyUniverse.length];
 153.134 +    }
 153.135 +
 153.136 +    /**
 153.137 +     * Creates an enum map with the same key type as the specified enum
 153.138 +     * map, initially containing the same mappings (if any).
 153.139 +     *
 153.140 +     * @param m the enum map from which to initialize this enum map
 153.141 +     * @throws NullPointerException if <tt>m</tt> is null
 153.142 +     */
 153.143 +    public EnumMap(EnumMap<K, ? extends V> m) {
 153.144 +        keyType = m.keyType;
 153.145 +        keyUniverse = m.keyUniverse;
 153.146 +        vals = m.vals.clone();
 153.147 +        size = m.size;
 153.148 +    }
 153.149 +
 153.150 +    /**
 153.151 +     * Creates an enum map initialized from the specified map.  If the
 153.152 +     * specified map is an <tt>EnumMap</tt> instance, this constructor behaves
 153.153 +     * identically to {@link #EnumMap(EnumMap)}.  Otherwise, the specified map
 153.154 +     * must contain at least one mapping (in order to determine the new
 153.155 +     * enum map's key type).
 153.156 +     *
 153.157 +     * @param m the map from which to initialize this enum map
 153.158 +     * @throws IllegalArgumentException if <tt>m</tt> is not an
 153.159 +     *     <tt>EnumMap</tt> instance and contains no mappings
 153.160 +     * @throws NullPointerException if <tt>m</tt> is null
 153.161 +     */
 153.162 +    public EnumMap(Map<K, ? extends V> m) {
 153.163 +        if (m instanceof EnumMap) {
 153.164 +            EnumMap<K, ? extends V> em = (EnumMap<K, ? extends V>) m;
 153.165 +            keyType = em.keyType;
 153.166 +            keyUniverse = em.keyUniverse;
 153.167 +            vals = em.vals.clone();
 153.168 +            size = em.size;
 153.169 +        } else {
 153.170 +            if (m.isEmpty())
 153.171 +                throw new IllegalArgumentException("Specified map is empty");
 153.172 +            keyType = m.keySet().iterator().next().getDeclaringClass();
 153.173 +            keyUniverse = getKeyUniverse(keyType);
 153.174 +            vals = new Object[keyUniverse.length];
 153.175 +            putAll(m);
 153.176 +        }
 153.177 +    }
 153.178 +
 153.179 +    // Query Operations
 153.180 +
 153.181 +    /**
 153.182 +     * Returns the number of key-value mappings in this map.
 153.183 +     *
 153.184 +     * @return the number of key-value mappings in this map
 153.185 +     */
 153.186 +    public int size() {
 153.187 +        return size;
 153.188 +    }
 153.189 +
 153.190 +    /**
 153.191 +     * Returns <tt>true</tt> if this map maps one or more keys to the
 153.192 +     * specified value.
 153.193 +     *
 153.194 +     * @param value the value whose presence in this map is to be tested
 153.195 +     * @return <tt>true</tt> if this map maps one or more keys to this value
 153.196 +     */
 153.197 +    public boolean containsValue(Object value) {
 153.198 +        value = maskNull(value);
 153.199 +
 153.200 +        for (Object val : vals)
 153.201 +            if (value.equals(val))
 153.202 +                return true;
 153.203 +
 153.204 +        return false;
 153.205 +    }
 153.206 +
 153.207 +    /**
 153.208 +     * Returns <tt>true</tt> if this map contains a mapping for the specified
 153.209 +     * key.
 153.210 +     *
 153.211 +     * @param key the key whose presence in this map is to be tested
 153.212 +     * @return <tt>true</tt> if this map contains a mapping for the specified
 153.213 +     *            key
 153.214 +     */
 153.215 +    public boolean containsKey(Object key) {
 153.216 +        return isValidKey(key) && vals[((Enum)key).ordinal()] != null;
 153.217 +    }
 153.218 +
 153.219 +    private boolean containsMapping(Object key, Object value) {
 153.220 +        return isValidKey(key) &&
 153.221 +            maskNull(value).equals(vals[((Enum)key).ordinal()]);
 153.222 +    }
 153.223 +
 153.224 +    /**
 153.225 +     * Returns the value to which the specified key is mapped,
 153.226 +     * or {@code null} if this map contains no mapping for the key.
 153.227 +     *
 153.228 +     * <p>More formally, if this map contains a mapping from a key
 153.229 +     * {@code k} to a value {@code v} such that {@code (key == k)},
 153.230 +     * then this method returns {@code v}; otherwise it returns
 153.231 +     * {@code null}.  (There can be at most one such mapping.)
 153.232 +     *
 153.233 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 153.234 +     * indicate that the map contains no mapping for the key; it's also
 153.235 +     * possible that the map explicitly maps the key to {@code null}.
 153.236 +     * The {@link #containsKey containsKey} operation may be used to
 153.237 +     * distinguish these two cases.
 153.238 +     */
 153.239 +    public V get(Object key) {
 153.240 +        return (isValidKey(key) ?
 153.241 +                unmaskNull(vals[((Enum)key).ordinal()]) : null);
 153.242 +    }
 153.243 +
 153.244 +    // Modification Operations
 153.245 +
 153.246 +    /**
 153.247 +     * Associates the specified value with the specified key in this map.
 153.248 +     * If the map previously contained a mapping for this key, the old
 153.249 +     * value is replaced.
 153.250 +     *
 153.251 +     * @param key the key with which the specified value is to be associated
 153.252 +     * @param value the value to be associated with the specified key
 153.253 +     *
 153.254 +     * @return the previous value associated with specified key, or
 153.255 +     *     <tt>null</tt> if there was no mapping for key.  (A <tt>null</tt>
 153.256 +     *     return can also indicate that the map previously associated
 153.257 +     *     <tt>null</tt> with the specified key.)
 153.258 +     * @throws NullPointerException if the specified key is null
 153.259 +     */
 153.260 +    public V put(K key, V value) {
 153.261 +        typeCheck(key);
 153.262 +
 153.263 +        int index = key.ordinal();
 153.264 +        Object oldValue = vals[index];
 153.265 +        vals[index] = maskNull(value);
 153.266 +        if (oldValue == null)
 153.267 +            size++;
 153.268 +        return unmaskNull(oldValue);
 153.269 +    }
 153.270 +
 153.271 +    /**
 153.272 +     * Removes the mapping for this key from this map if present.
 153.273 +     *
 153.274 +     * @param key the key whose mapping is to be removed from the map
 153.275 +     * @return the previous value associated with specified key, or
 153.276 +     *     <tt>null</tt> if there was no entry for key.  (A <tt>null</tt>
 153.277 +     *     return can also indicate that the map previously associated
 153.278 +     *     <tt>null</tt> with the specified key.)
 153.279 +     */
 153.280 +    public V remove(Object key) {
 153.281 +        if (!isValidKey(key))
 153.282 +            return null;
 153.283 +        int index = ((Enum)key).ordinal();
 153.284 +        Object oldValue = vals[index];
 153.285 +        vals[index] = null;
 153.286 +        if (oldValue != null)
 153.287 +            size--;
 153.288 +        return unmaskNull(oldValue);
 153.289 +    }
 153.290 +
 153.291 +    private boolean removeMapping(Object key, Object value) {
 153.292 +        if (!isValidKey(key))
 153.293 +            return false;
 153.294 +        int index = ((Enum)key).ordinal();
 153.295 +        if (maskNull(value).equals(vals[index])) {
 153.296 +            vals[index] = null;
 153.297 +            size--;
 153.298 +            return true;
 153.299 +        }
 153.300 +        return false;
 153.301 +    }
 153.302 +
 153.303 +    /**
 153.304 +     * Returns true if key is of the proper type to be a key in this
 153.305 +     * enum map.
 153.306 +     */
 153.307 +    private boolean isValidKey(Object key) {
 153.308 +        if (key == null)
 153.309 +            return false;
 153.310 +
 153.311 +        // Cheaper than instanceof Enum followed by getDeclaringClass
 153.312 +        Class keyClass = key.getClass();
 153.313 +        return keyClass == keyType || keyClass.getSuperclass() == keyType;
 153.314 +    }
 153.315 +
 153.316 +    // Bulk Operations
 153.317 +
 153.318 +    /**
 153.319 +     * Copies all of the mappings from the specified map to this map.
 153.320 +     * These mappings will replace any mappings that this map had for
 153.321 +     * any of the keys currently in the specified map.
 153.322 +     *
 153.323 +     * @param m the mappings to be stored in this map
 153.324 +     * @throws NullPointerException the specified map is null, or if
 153.325 +     *     one or more keys in the specified map are null
 153.326 +     */
 153.327 +    public void putAll(Map<? extends K, ? extends V> m) {
 153.328 +        if (m instanceof EnumMap) {
 153.329 +            EnumMap<? extends K, ? extends V> em =
 153.330 +                (EnumMap<? extends K, ? extends V>)m;
 153.331 +            if (em.keyType != keyType) {
 153.332 +                if (em.isEmpty())
 153.333 +                    return;
 153.334 +                throw new ClassCastException(em.keyType + " != " + keyType);
 153.335 +            }
 153.336 +
 153.337 +            for (int i = 0; i < keyUniverse.length; i++) {
 153.338 +                Object emValue = em.vals[i];
 153.339 +                if (emValue != null) {
 153.340 +                    if (vals[i] == null)
 153.341 +                        size++;
 153.342 +                    vals[i] = emValue;
 153.343 +                }
 153.344 +            }
 153.345 +        } else {
 153.346 +            super.putAll(m);
 153.347 +        }
 153.348 +    }
 153.349 +
 153.350 +    /**
 153.351 +     * Removes all mappings from this map.
 153.352 +     */
 153.353 +    public void clear() {
 153.354 +        Arrays.fill(vals, null);
 153.355 +        size = 0;
 153.356 +    }
 153.357 +
 153.358 +    // Views
 153.359 +
 153.360 +    /**
 153.361 +     * This field is initialized to contain an instance of the entry set
 153.362 +     * view the first time this view is requested.  The view is stateless,
 153.363 +     * so there's no reason to create more than one.
 153.364 +     */
 153.365 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 153.366 +
 153.367 +    /**
 153.368 +     * Returns a {@link Set} view of the keys contained in this map.
 153.369 +     * The returned set obeys the general contract outlined in
 153.370 +     * {@link Map#keySet()}.  The set's iterator will return the keys
 153.371 +     * in their natural order (the order in which the enum constants
 153.372 +     * are declared).
 153.373 +     *
 153.374 +     * @return a set view of the keys contained in this enum map
 153.375 +     */
 153.376 +    public Set<K> keySet() {
 153.377 +        Set<K> ks = keySet;
 153.378 +        if (ks != null)
 153.379 +            return ks;
 153.380 +        else
 153.381 +            return keySet = new KeySet();
 153.382 +    }
 153.383 +
 153.384 +    private class KeySet extends AbstractSet<K> {
 153.385 +        public Iterator<K> iterator() {
 153.386 +            return new KeyIterator();
 153.387 +        }
 153.388 +        public int size() {
 153.389 +            return size;
 153.390 +        }
 153.391 +        public boolean contains(Object o) {
 153.392 +            return containsKey(o);
 153.393 +        }
 153.394 +        public boolean remove(Object o) {
 153.395 +            int oldSize = size;
 153.396 +            EnumMap.this.remove(o);
 153.397 +            return size != oldSize;
 153.398 +        }
 153.399 +        public void clear() {
 153.400 +            EnumMap.this.clear();
 153.401 +        }
 153.402 +    }
 153.403 +
 153.404 +    /**
 153.405 +     * Returns a {@link Collection} view of the values contained in this map.
 153.406 +     * The returned collection obeys the general contract outlined in
 153.407 +     * {@link Map#values()}.  The collection's iterator will return the
 153.408 +     * values in the order their corresponding keys appear in map,
 153.409 +     * which is their natural order (the order in which the enum constants
 153.410 +     * are declared).
 153.411 +     *
 153.412 +     * @return a collection view of the values contained in this map
 153.413 +     */
 153.414 +    public Collection<V> values() {
 153.415 +        Collection<V> vs = values;
 153.416 +        if (vs != null)
 153.417 +            return vs;
 153.418 +        else
 153.419 +            return values = new Values();
 153.420 +    }
 153.421 +
 153.422 +    private class Values extends AbstractCollection<V> {
 153.423 +        public Iterator<V> iterator() {
 153.424 +            return new ValueIterator();
 153.425 +        }
 153.426 +        public int size() {
 153.427 +            return size;
 153.428 +        }
 153.429 +        public boolean contains(Object o) {
 153.430 +            return containsValue(o);
 153.431 +        }
 153.432 +        public boolean remove(Object o) {
 153.433 +            o = maskNull(o);
 153.434 +
 153.435 +            for (int i = 0; i < vals.length; i++) {
 153.436 +                if (o.equals(vals[i])) {
 153.437 +                    vals[i] = null;
 153.438 +                    size--;
 153.439 +                    return true;
 153.440 +                }
 153.441 +            }
 153.442 +            return false;
 153.443 +        }
 153.444 +        public void clear() {
 153.445 +            EnumMap.this.clear();
 153.446 +        }
 153.447 +    }
 153.448 +
 153.449 +    /**
 153.450 +     * Returns a {@link Set} view of the mappings contained in this map.
 153.451 +     * The returned set obeys the general contract outlined in
 153.452 +     * {@link Map#keySet()}.  The set's iterator will return the
 153.453 +     * mappings in the order their keys appear in map, which is their
 153.454 +     * natural order (the order in which the enum constants are declared).
 153.455 +     *
 153.456 +     * @return a set view of the mappings contained in this enum map
 153.457 +     */
 153.458 +    public Set<Map.Entry<K,V>> entrySet() {
 153.459 +        Set<Map.Entry<K,V>> es = entrySet;
 153.460 +        if (es != null)
 153.461 +            return es;
 153.462 +        else
 153.463 +            return entrySet = new EntrySet();
 153.464 +    }
 153.465 +
 153.466 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 153.467 +        public Iterator<Map.Entry<K,V>> iterator() {
 153.468 +            return new EntryIterator();
 153.469 +        }
 153.470 +
 153.471 +        public boolean contains(Object o) {
 153.472 +            if (!(o instanceof Map.Entry))
 153.473 +                return false;
 153.474 +            Map.Entry entry = (Map.Entry)o;
 153.475 +            return containsMapping(entry.getKey(), entry.getValue());
 153.476 +        }
 153.477 +        public boolean remove(Object o) {
 153.478 +            if (!(o instanceof Map.Entry))
 153.479 +                return false;
 153.480 +            Map.Entry entry = (Map.Entry)o;
 153.481 +            return removeMapping(entry.getKey(), entry.getValue());
 153.482 +        }
 153.483 +        public int size() {
 153.484 +            return size;
 153.485 +        }
 153.486 +        public void clear() {
 153.487 +            EnumMap.this.clear();
 153.488 +        }
 153.489 +        public Object[] toArray() {
 153.490 +            return fillEntryArray(new Object[size]);
 153.491 +        }
 153.492 +        @SuppressWarnings("unchecked")
 153.493 +        public <T> T[] toArray(T[] a) {
 153.494 +            int size = size();
 153.495 +            if (a.length < size)
 153.496 +                a = (T[])java.lang.reflect.Array
 153.497 +                    .newInstance(a.getClass().getComponentType(), size);
 153.498 +            if (a.length > size)
 153.499 +                a[size] = null;
 153.500 +            return (T[]) fillEntryArray(a);
 153.501 +        }
 153.502 +        private Object[] fillEntryArray(Object[] a) {
 153.503 +            int j = 0;
 153.504 +            for (int i = 0; i < vals.length; i++)
 153.505 +                if (vals[i] != null)
 153.506 +                    a[j++] = new AbstractMap.SimpleEntry<>(
 153.507 +                        keyUniverse[i], unmaskNull(vals[i]));
 153.508 +            return a;
 153.509 +        }
 153.510 +    }
 153.511 +
 153.512 +    private abstract class EnumMapIterator<T> implements Iterator<T> {
 153.513 +        // Lower bound on index of next element to return
 153.514 +        int index = 0;
 153.515 +
 153.516 +        // Index of last returned element, or -1 if none
 153.517 +        int lastReturnedIndex = -1;
 153.518 +
 153.519 +        public boolean hasNext() {
 153.520 +            while (index < vals.length && vals[index] == null)
 153.521 +                index++;
 153.522 +            return index != vals.length;
 153.523 +        }
 153.524 +
 153.525 +        public void remove() {
 153.526 +            checkLastReturnedIndex();
 153.527 +
 153.528 +            if (vals[lastReturnedIndex] != null) {
 153.529 +                vals[lastReturnedIndex] = null;
 153.530 +                size--;
 153.531 +            }
 153.532 +            lastReturnedIndex = -1;
 153.533 +        }
 153.534 +
 153.535 +        private void checkLastReturnedIndex() {
 153.536 +            if (lastReturnedIndex < 0)
 153.537 +                throw new IllegalStateException();
 153.538 +        }
 153.539 +    }
 153.540 +
 153.541 +    private class KeyIterator extends EnumMapIterator<K> {
 153.542 +        public K next() {
 153.543 +            if (!hasNext())
 153.544 +                throw new NoSuchElementException();
 153.545 +            lastReturnedIndex = index++;
 153.546 +            return keyUniverse[lastReturnedIndex];
 153.547 +        }
 153.548 +    }
 153.549 +
 153.550 +    private class ValueIterator extends EnumMapIterator<V> {
 153.551 +        public V next() {
 153.552 +            if (!hasNext())
 153.553 +                throw new NoSuchElementException();
 153.554 +            lastReturnedIndex = index++;
 153.555 +            return unmaskNull(vals[lastReturnedIndex]);
 153.556 +        }
 153.557 +    }
 153.558 +
 153.559 +    private class EntryIterator extends EnumMapIterator<Map.Entry<K,V>> {
 153.560 +        private Entry lastReturnedEntry = null;
 153.561 +
 153.562 +        public Map.Entry<K,V> next() {
 153.563 +            if (!hasNext())
 153.564 +                throw new NoSuchElementException();
 153.565 +            lastReturnedEntry = new Entry(index++);
 153.566 +            return lastReturnedEntry;
 153.567 +        }
 153.568 +
 153.569 +        public void remove() {
 153.570 +            lastReturnedIndex =
 153.571 +                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
 153.572 +            super.remove();
 153.573 +            lastReturnedEntry.index = lastReturnedIndex;
 153.574 +            lastReturnedEntry = null;
 153.575 +        }
 153.576 +
 153.577 +        private class Entry implements Map.Entry<K,V> {
 153.578 +            private int index;
 153.579 +
 153.580 +            private Entry(int index) {
 153.581 +                this.index = index;
 153.582 +            }
 153.583 +
 153.584 +            public K getKey() {
 153.585 +                checkIndexForEntryUse();
 153.586 +                return keyUniverse[index];
 153.587 +            }
 153.588 +
 153.589 +            public V getValue() {
 153.590 +                checkIndexForEntryUse();
 153.591 +                return unmaskNull(vals[index]);
 153.592 +            }
 153.593 +
 153.594 +            public V setValue(V value) {
 153.595 +                checkIndexForEntryUse();
 153.596 +                V oldValue = unmaskNull(vals[index]);
 153.597 +                vals[index] = maskNull(value);
 153.598 +                return oldValue;
 153.599 +            }
 153.600 +
 153.601 +            public boolean equals(Object o) {
 153.602 +                if (index < 0)
 153.603 +                    return o == this;
 153.604 +
 153.605 +                if (!(o instanceof Map.Entry))
 153.606 +                    return false;
 153.607 +
 153.608 +                Map.Entry e = (Map.Entry)o;
 153.609 +                V ourValue = unmaskNull(vals[index]);
 153.610 +                Object hisValue = e.getValue();
 153.611 +                return (e.getKey() == keyUniverse[index] &&
 153.612 +                        (ourValue == hisValue ||
 153.613 +                         (ourValue != null && ourValue.equals(hisValue))));
 153.614 +            }
 153.615 +
 153.616 +            public int hashCode() {
 153.617 +                if (index < 0)
 153.618 +                    return super.hashCode();
 153.619 +
 153.620 +                return entryHashCode(index);
 153.621 +            }
 153.622 +
 153.623 +            public String toString() {
 153.624 +                if (index < 0)
 153.625 +                    return super.toString();
 153.626 +
 153.627 +                return keyUniverse[index] + "="
 153.628 +                    + unmaskNull(vals[index]);
 153.629 +            }
 153.630 +
 153.631 +            private void checkIndexForEntryUse() {
 153.632 +                if (index < 0)
 153.633 +                    throw new IllegalStateException("Entry was removed");
 153.634 +            }
 153.635 +        }
 153.636 +    }
 153.637 +
 153.638 +    // Comparison and hashing
 153.639 +
 153.640 +    /**
 153.641 +     * Compares the specified object with this map for equality.  Returns
 153.642 +     * <tt>true</tt> if the given object is also a map and the two maps
 153.643 +     * represent the same mappings, as specified in the {@link
 153.644 +     * Map#equals(Object)} contract.
 153.645 +     *
 153.646 +     * @param o the object to be compared for equality with this map
 153.647 +     * @return <tt>true</tt> if the specified object is equal to this map
 153.648 +     */
 153.649 +    public boolean equals(Object o) {
 153.650 +        if (this == o)
 153.651 +            return true;
 153.652 +        if (o instanceof EnumMap)
 153.653 +            return equals((EnumMap)o);
 153.654 +        if (!(o instanceof Map))
 153.655 +            return false;
 153.656 +
 153.657 +        Map<K,V> m = (Map<K,V>)o;
 153.658 +        if (size != m.size())
 153.659 +            return false;
 153.660 +
 153.661 +        for (int i = 0; i < keyUniverse.length; i++) {
 153.662 +            if (null != vals[i]) {
 153.663 +                K key = keyUniverse[i];
 153.664 +                V value = unmaskNull(vals[i]);
 153.665 +                if (null == value) {
 153.666 +                    if (!((null == m.get(key)) && m.containsKey(key)))
 153.667 +                       return false;
 153.668 +                } else {
 153.669 +                   if (!value.equals(m.get(key)))
 153.670 +                      return false;
 153.671 +                }
 153.672 +            }
 153.673 +        }
 153.674 +
 153.675 +        return true;
 153.676 +    }
 153.677 +
 153.678 +    private boolean equals(EnumMap em) {
 153.679 +        if (em.keyType != keyType)
 153.680 +            return size == 0 && em.size == 0;
 153.681 +
 153.682 +        // Key types match, compare each value
 153.683 +        for (int i = 0; i < keyUniverse.length; i++) {
 153.684 +            Object ourValue =    vals[i];
 153.685 +            Object hisValue = em.vals[i];
 153.686 +            if (hisValue != ourValue &&
 153.687 +                (hisValue == null || !hisValue.equals(ourValue)))
 153.688 +                return false;
 153.689 +        }
 153.690 +        return true;
 153.691 +    }
 153.692 +
 153.693 +    /**
 153.694 +     * Returns the hash code value for this map.  The hash code of a map is
 153.695 +     * defined to be the sum of the hash codes of each entry in the map.
 153.696 +     */
 153.697 +    public int hashCode() {
 153.698 +        int h = 0;
 153.699 +
 153.700 +        for (int i = 0; i < keyUniverse.length; i++) {
 153.701 +            if (null != vals[i]) {
 153.702 +                h += entryHashCode(i);
 153.703 +            }
 153.704 +        }
 153.705 +
 153.706 +        return h;
 153.707 +    }
 153.708 +
 153.709 +    private int entryHashCode(int index) {
 153.710 +        return (keyUniverse[index].hashCode() ^ vals[index].hashCode());
 153.711 +    }
 153.712 +
 153.713 +    /**
 153.714 +     * Returns a shallow copy of this enum map.  (The values themselves
 153.715 +     * are not cloned.
 153.716 +     *
 153.717 +     * @return a shallow copy of this enum map
 153.718 +     */
 153.719 +    public EnumMap<K, V> clone() {
 153.720 +        EnumMap<K, V> result = null;
 153.721 +        try {
 153.722 +            result = (EnumMap<K, V>) super.clone();
 153.723 +        } catch(CloneNotSupportedException e) {
 153.724 +            throw new AssertionError();
 153.725 +        }
 153.726 +        result.vals = result.vals.clone();
 153.727 +        return result;
 153.728 +    }
 153.729 +
 153.730 +    /**
 153.731 +     * Throws an exception if e is not of the correct type for this enum set.
 153.732 +     */
 153.733 +    private void typeCheck(K key) {
 153.734 +        Class keyClass = key.getClass();
 153.735 +        if (keyClass != keyType && keyClass.getSuperclass() != keyType)
 153.736 +            throw new ClassCastException(keyClass + " != " + keyType);
 153.737 +    }
 153.738 +
 153.739 +    /**
 153.740 +     * Returns all of the values comprising K.
 153.741 +     * The result is uncloned, cached, and shared by all callers.
 153.742 +     */
 153.743 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
 153.744 +    private static native <K extends Enum<K>> K[] getKeyUniverse(Class<K> keyType);
 153.745 +
 153.746 +    private static final long serialVersionUID = 458661240069192865L;
 153.747 +
 153.748 +    /**
 153.749 +     * Save the state of the <tt>EnumMap</tt> instance to a stream (i.e.,
 153.750 +     * serialize it).
 153.751 +     *
 153.752 +     * @serialData The <i>size</i> of the enum map (the number of key-value
 153.753 +     *             mappings) is emitted (int), followed by the key (Object)
 153.754 +     *             and value (Object) for each key-value mapping represented
 153.755 +     *             by the enum map.
 153.756 +     */
 153.757 +    private void writeObject(java.io.ObjectOutputStream s)
 153.758 +        throws java.io.IOException
 153.759 +    {
 153.760 +        // Write out the key type and any hidden stuff
 153.761 +        s.defaultWriteObject();
 153.762 +
 153.763 +        // Write out size (number of Mappings)
 153.764 +        s.writeInt(size);
 153.765 +
 153.766 +        // Write out keys and values (alternating)
 153.767 +        int entriesToBeWritten = size;
 153.768 +        for (int i = 0; entriesToBeWritten > 0; i++) {
 153.769 +            if (null != vals[i]) {
 153.770 +                s.writeObject(keyUniverse[i]);
 153.771 +                s.writeObject(unmaskNull(vals[i]));
 153.772 +                entriesToBeWritten--;
 153.773 +            }
 153.774 +        }
 153.775 +    }
 153.776 +
 153.777 +    /**
 153.778 +     * Reconstitute the <tt>EnumMap</tt> instance from a stream (i.e.,
 153.779 +     * deserialize it).
 153.780 +     */
 153.781 +    private void readObject(java.io.ObjectInputStream s)
 153.782 +        throws java.io.IOException, ClassNotFoundException
 153.783 +    {
 153.784 +        // Read in the key type and any hidden stuff
 153.785 +        s.defaultReadObject();
 153.786 +
 153.787 +        keyUniverse = getKeyUniverse(keyType);
 153.788 +        vals = new Object[keyUniverse.length];
 153.789 +
 153.790 +        // Read in size (number of Mappings)
 153.791 +        int size = s.readInt();
 153.792 +
 153.793 +        // Read the keys and values, and put the mappings in the HashMap
 153.794 +        for (int i = 0; i < size; i++) {
 153.795 +            K key = (K) s.readObject();
 153.796 +            V value = (V) s.readObject();
 153.797 +            put(key, value);
 153.798 +        }
 153.799 +    }
 153.800 +}
   154.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   154.2 +++ b/rt/emul/compact/src/main/java/java/util/EnumSet.java	Mon Oct 07 14:20:58 2013 +0200
   154.3 @@ -0,0 +1,441 @@
   154.4 +/*
   154.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   154.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   154.7 + *
   154.8 + * This code is free software; you can redistribute it and/or modify it
   154.9 + * under the terms of the GNU General Public License version 2 only, as
  154.10 + * published by the Free Software Foundation.  Oracle designates this
  154.11 + * particular file as subject to the "Classpath" exception as provided
  154.12 + * by Oracle in the LICENSE file that accompanied this code.
  154.13 + *
  154.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  154.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  154.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  154.17 + * version 2 for more details (a copy is included in the LICENSE file that
  154.18 + * accompanied this code).
  154.19 + *
  154.20 + * You should have received a copy of the GNU General Public License version
  154.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  154.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  154.23 + *
  154.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  154.25 + * or visit www.oracle.com if you need additional information or have any
  154.26 + * questions.
  154.27 + */
  154.28 +
  154.29 +package java.util;
  154.30 +
  154.31 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  154.32 +
  154.33 +/**
  154.34 + * A specialized {@link Set} implementation for use with enum types.  All of
  154.35 + * the elements in an enum set must come from a single enum type that is
  154.36 + * specified, explicitly or implicitly, when the set is created.  Enum sets
  154.37 + * are represented internally as bit vectors.  This representation is
  154.38 + * extremely compact and efficient. The space and time performance of this
  154.39 + * class should be good enough to allow its use as a high-quality, typesafe
  154.40 + * alternative to traditional <tt>int</tt>-based "bit flags."  Even bulk
  154.41 + * operations (such as <tt>containsAll</tt> and <tt>retainAll</tt>) should
  154.42 + * run very quickly if their argument is also an enum set.
  154.43 + *
  154.44 + * <p>The iterator returned by the <tt>iterator</tt> method traverses the
  154.45 + * elements in their <i>natural order</i> (the order in which the enum
  154.46 + * constants are declared).  The returned iterator is <i>weakly
  154.47 + * consistent</i>: it will never throw {@link ConcurrentModificationException}
  154.48 + * and it may or may not show the effects of any modifications to the set that
  154.49 + * occur while the iteration is in progress.
  154.50 + *
  154.51 + * <p>Null elements are not permitted.  Attempts to insert a null element
  154.52 + * will throw {@link NullPointerException}.  Attempts to test for the
  154.53 + * presence of a null element or to remove one will, however, function
  154.54 + * properly.
  154.55 + *
  154.56 + * <P>Like most collection implementations, <tt>EnumSet</tt> is not
  154.57 + * synchronized.  If multiple threads access an enum set concurrently, and at
  154.58 + * least one of the threads modifies the set, it should be synchronized
  154.59 + * externally.  This is typically accomplished by synchronizing on some
  154.60 + * object that naturally encapsulates the enum set.  If no such object exists,
  154.61 + * the set should be "wrapped" using the {@link Collections#synchronizedSet}
  154.62 + * method.  This is best done at creation time, to prevent accidental
  154.63 + * unsynchronized access:
  154.64 + *
  154.65 + * <pre>
  154.66 + * Set&lt;MyEnum&gt; s = Collections.synchronizedSet(EnumSet.noneOf(MyEnum.class));
  154.67 + * </pre>
  154.68 + *
  154.69 + * <p>Implementation note: All basic operations execute in constant time.
  154.70 + * They are likely (though not guaranteed) to be much faster than their
  154.71 + * {@link HashSet} counterparts.  Even bulk operations execute in
  154.72 + * constant time if their argument is also an enum set.
  154.73 + *
  154.74 + * <p>This class is a member of the
  154.75 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  154.76 + * Java Collections Framework</a>.
  154.77 + *
  154.78 + * @author Josh Bloch
  154.79 + * @since 1.5
  154.80 + * @see EnumMap
  154.81 + * @serial exclude
  154.82 + */
  154.83 +public abstract class EnumSet<E extends Enum<E>> extends AbstractSet<E>
  154.84 +    implements Cloneable, java.io.Serializable
  154.85 +{
  154.86 +    /**
  154.87 +     * The class of all the elements of this set.
  154.88 +     */
  154.89 +    final Class<E> elementType;
  154.90 +
  154.91 +    /**
  154.92 +     * All of the values comprising T.  (Cached for performance.)
  154.93 +     */
  154.94 +    final Enum[] universe;
  154.95 +
  154.96 +    private static Enum[] ZERO_LENGTH_ENUM_ARRAY = new Enum[0];
  154.97 +
  154.98 +    EnumSet(Class<E>elementType, Enum[] universe) {
  154.99 +        this.elementType = elementType;
 154.100 +        this.universe    = universe;
 154.101 +    }
 154.102 +
 154.103 +    /**
 154.104 +     * Creates an empty enum set with the specified element type.
 154.105 +     *
 154.106 +     * @param elementType the class object of the element type for this enum
 154.107 +     *     set
 154.108 +     * @throws NullPointerException if <tt>elementType</tt> is null
 154.109 +     */
 154.110 +    public static <E extends Enum<E>> EnumSet<E> noneOf(Class<E> elementType) {
 154.111 +        Enum[] universe = getUniverse(elementType);
 154.112 +        if (universe == null)
 154.113 +            throw new ClassCastException(elementType + " not an enum");
 154.114 +
 154.115 +        if (universe.length <= 64)
 154.116 +            return new RegularEnumSet<>(elementType, universe);
 154.117 +        else
 154.118 +            return new JumboEnumSet<>(elementType, universe);
 154.119 +    }
 154.120 +
 154.121 +    /**
 154.122 +     * Creates an enum set containing all of the elements in the specified
 154.123 +     * element type.
 154.124 +     *
 154.125 +     * @param elementType the class object of the element type for this enum
 154.126 +     *     set
 154.127 +     * @throws NullPointerException if <tt>elementType</tt> is null
 154.128 +     */
 154.129 +    public static <E extends Enum<E>> EnumSet<E> allOf(Class<E> elementType) {
 154.130 +        EnumSet<E> result = noneOf(elementType);
 154.131 +        result.addAll();
 154.132 +        return result;
 154.133 +    }
 154.134 +
 154.135 +    /**
 154.136 +     * Adds all of the elements from the appropriate enum type to this enum
 154.137 +     * set, which is empty prior to the call.
 154.138 +     */
 154.139 +    abstract void addAll();
 154.140 +
 154.141 +    /**
 154.142 +     * Creates an enum set with the same element type as the specified enum
 154.143 +     * set, initially containing the same elements (if any).
 154.144 +     *
 154.145 +     * @param s the enum set from which to initialize this enum set
 154.146 +     * @throws NullPointerException if <tt>s</tt> is null
 154.147 +     */
 154.148 +    public static <E extends Enum<E>> EnumSet<E> copyOf(EnumSet<E> s) {
 154.149 +        return s.clone();
 154.150 +    }
 154.151 +
 154.152 +    /**
 154.153 +     * Creates an enum set initialized from the specified collection.  If
 154.154 +     * the specified collection is an <tt>EnumSet</tt> instance, this static
 154.155 +     * factory method behaves identically to {@link #copyOf(EnumSet)}.
 154.156 +     * Otherwise, the specified collection must contain at least one element
 154.157 +     * (in order to determine the new enum set's element type).
 154.158 +     *
 154.159 +     * @param c the collection from which to initialize this enum set
 154.160 +     * @throws IllegalArgumentException if <tt>c</tt> is not an
 154.161 +     *     <tt>EnumSet</tt> instance and contains no elements
 154.162 +     * @throws NullPointerException if <tt>c</tt> is null
 154.163 +     */
 154.164 +    public static <E extends Enum<E>> EnumSet<E> copyOf(Collection<E> c) {
 154.165 +        if (c instanceof EnumSet) {
 154.166 +            return ((EnumSet<E>)c).clone();
 154.167 +        } else {
 154.168 +            if (c.isEmpty())
 154.169 +                throw new IllegalArgumentException("Collection is empty");
 154.170 +            Iterator<E> i = c.iterator();
 154.171 +            E first = i.next();
 154.172 +            EnumSet<E> result = EnumSet.of(first);
 154.173 +            while (i.hasNext())
 154.174 +                result.add(i.next());
 154.175 +            return result;
 154.176 +        }
 154.177 +    }
 154.178 +
 154.179 +    /**
 154.180 +     * Creates an enum set with the same element type as the specified enum
 154.181 +     * set, initially containing all the elements of this type that are
 154.182 +     * <i>not</i> contained in the specified set.
 154.183 +     *
 154.184 +     * @param s the enum set from whose complement to initialize this enum set
 154.185 +     * @throws NullPointerException if <tt>s</tt> is null
 154.186 +     */
 154.187 +    public static <E extends Enum<E>> EnumSet<E> complementOf(EnumSet<E> s) {
 154.188 +        EnumSet<E> result = copyOf(s);
 154.189 +        result.complement();
 154.190 +        return result;
 154.191 +    }
 154.192 +
 154.193 +    /**
 154.194 +     * Creates an enum set initially containing the specified element.
 154.195 +     *
 154.196 +     * Overloadings of this method exist to initialize an enum set with
 154.197 +     * one through five elements.  A sixth overloading is provided that
 154.198 +     * uses the varargs feature.  This overloading may be used to create
 154.199 +     * an enum set initially containing an arbitrary number of elements, but
 154.200 +     * is likely to run slower than the overloadings that do not use varargs.
 154.201 +     *
 154.202 +     * @param e the element that this set is to contain initially
 154.203 +     * @throws NullPointerException if <tt>e</tt> is null
 154.204 +     * @return an enum set initially containing the specified element
 154.205 +     */
 154.206 +    public static <E extends Enum<E>> EnumSet<E> of(E e) {
 154.207 +        EnumSet<E> result = noneOf(e.getDeclaringClass());
 154.208 +        result.add(e);
 154.209 +        return result;
 154.210 +    }
 154.211 +
 154.212 +    /**
 154.213 +     * Creates an enum set initially containing the specified elements.
 154.214 +     *
 154.215 +     * Overloadings of this method exist to initialize an enum set with
 154.216 +     * one through five elements.  A sixth overloading is provided that
 154.217 +     * uses the varargs feature.  This overloading may be used to create
 154.218 +     * an enum set initially containing an arbitrary number of elements, but
 154.219 +     * is likely to run slower than the overloadings that do not use varargs.
 154.220 +     *
 154.221 +     * @param e1 an element that this set is to contain initially
 154.222 +     * @param e2 another element that this set is to contain initially
 154.223 +     * @throws NullPointerException if any parameters are null
 154.224 +     * @return an enum set initially containing the specified elements
 154.225 +     */
 154.226 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2) {
 154.227 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 154.228 +        result.add(e1);
 154.229 +        result.add(e2);
 154.230 +        return result;
 154.231 +    }
 154.232 +
 154.233 +    /**
 154.234 +     * Creates an enum set initially containing the specified elements.
 154.235 +     *
 154.236 +     * Overloadings of this method exist to initialize an enum set with
 154.237 +     * one through five elements.  A sixth overloading is provided that
 154.238 +     * uses the varargs feature.  This overloading may be used to create
 154.239 +     * an enum set initially containing an arbitrary number of elements, but
 154.240 +     * is likely to run slower than the overloadings that do not use varargs.
 154.241 +     *
 154.242 +     * @param e1 an element that this set is to contain initially
 154.243 +     * @param e2 another element that this set is to contain initially
 154.244 +     * @param e3 another element that this set is to contain initially
 154.245 +     * @throws NullPointerException if any parameters are null
 154.246 +     * @return an enum set initially containing the specified elements
 154.247 +     */
 154.248 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3) {
 154.249 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 154.250 +        result.add(e1);
 154.251 +        result.add(e2);
 154.252 +        result.add(e3);
 154.253 +        return result;
 154.254 +    }
 154.255 +
 154.256 +    /**
 154.257 +     * Creates an enum set initially containing the specified elements.
 154.258 +     *
 154.259 +     * Overloadings of this method exist to initialize an enum set with
 154.260 +     * one through five elements.  A sixth overloading is provided that
 154.261 +     * uses the varargs feature.  This overloading may be used to create
 154.262 +     * an enum set initially containing an arbitrary number of elements, but
 154.263 +     * is likely to run slower than the overloadings that do not use varargs.
 154.264 +     *
 154.265 +     * @param e1 an element that this set is to contain initially
 154.266 +     * @param e2 another element that this set is to contain initially
 154.267 +     * @param e3 another element that this set is to contain initially
 154.268 +     * @param e4 another element that this set is to contain initially
 154.269 +     * @throws NullPointerException if any parameters are null
 154.270 +     * @return an enum set initially containing the specified elements
 154.271 +     */
 154.272 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4) {
 154.273 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 154.274 +        result.add(e1);
 154.275 +        result.add(e2);
 154.276 +        result.add(e3);
 154.277 +        result.add(e4);
 154.278 +        return result;
 154.279 +    }
 154.280 +
 154.281 +    /**
 154.282 +     * Creates an enum set initially containing the specified elements.
 154.283 +     *
 154.284 +     * Overloadings of this method exist to initialize an enum set with
 154.285 +     * one through five elements.  A sixth overloading is provided that
 154.286 +     * uses the varargs feature.  This overloading may be used to create
 154.287 +     * an enum set initially containing an arbitrary number of elements, but
 154.288 +     * is likely to run slower than the overloadings that do not use varargs.
 154.289 +     *
 154.290 +     * @param e1 an element that this set is to contain initially
 154.291 +     * @param e2 another element that this set is to contain initially
 154.292 +     * @param e3 another element that this set is to contain initially
 154.293 +     * @param e4 another element that this set is to contain initially
 154.294 +     * @param e5 another element that this set is to contain initially
 154.295 +     * @throws NullPointerException if any parameters are null
 154.296 +     * @return an enum set initially containing the specified elements
 154.297 +     */
 154.298 +    public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4,
 154.299 +                                                    E e5)
 154.300 +    {
 154.301 +        EnumSet<E> result = noneOf(e1.getDeclaringClass());
 154.302 +        result.add(e1);
 154.303 +        result.add(e2);
 154.304 +        result.add(e3);
 154.305 +        result.add(e4);
 154.306 +        result.add(e5);
 154.307 +        return result;
 154.308 +    }
 154.309 +
 154.310 +    /**
 154.311 +     * Creates an enum set initially containing the specified elements.
 154.312 +     * This factory, whose parameter list uses the varargs feature, may
 154.313 +     * be used to create an enum set initially containing an arbitrary
 154.314 +     * number of elements, but it is likely to run slower than the overloadings
 154.315 +     * that do not use varargs.
 154.316 +     *
 154.317 +     * @param first an element that the set is to contain initially
 154.318 +     * @param rest the remaining elements the set is to contain initially
 154.319 +     * @throws NullPointerException if any of the specified elements are null,
 154.320 +     *     or if <tt>rest</tt> is null
 154.321 +     * @return an enum set initially containing the specified elements
 154.322 +     */
 154.323 +    @SafeVarargs
 154.324 +    public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
 154.325 +        EnumSet<E> result = noneOf(first.getDeclaringClass());
 154.326 +        result.add(first);
 154.327 +        for (E e : rest)
 154.328 +            result.add(e);
 154.329 +        return result;
 154.330 +    }
 154.331 +
 154.332 +    /**
 154.333 +     * Creates an enum set initially containing all of the elements in the
 154.334 +     * range defined by the two specified endpoints.  The returned set will
 154.335 +     * contain the endpoints themselves, which may be identical but must not
 154.336 +     * be out of order.
 154.337 +     *
 154.338 +     * @param from the first element in the range
 154.339 +     * @param to the last element in the range
 154.340 +     * @throws NullPointerException if {@code from} or {@code to} are null
 154.341 +     * @throws IllegalArgumentException if {@code from.compareTo(to) > 0}
 154.342 +     * @return an enum set initially containing all of the elements in the
 154.343 +     *         range defined by the two specified endpoints
 154.344 +     */
 154.345 +    public static <E extends Enum<E>> EnumSet<E> range(E from, E to) {
 154.346 +        if (from.compareTo(to) > 0)
 154.347 +            throw new IllegalArgumentException(from + " > " + to);
 154.348 +        EnumSet<E> result = noneOf(from.getDeclaringClass());
 154.349 +        result.addRange(from, to);
 154.350 +        return result;
 154.351 +    }
 154.352 +
 154.353 +    /**
 154.354 +     * Adds the specified range to this enum set, which is empty prior
 154.355 +     * to the call.
 154.356 +     */
 154.357 +    abstract void addRange(E from, E to);
 154.358 +
 154.359 +    /**
 154.360 +     * Returns a copy of this set.
 154.361 +     *
 154.362 +     * @return a copy of this set
 154.363 +     */
 154.364 +    public EnumSet<E> clone() {
 154.365 +        try {
 154.366 +            return (EnumSet<E>) super.clone();
 154.367 +        } catch(CloneNotSupportedException e) {
 154.368 +            throw new AssertionError(e);
 154.369 +        }
 154.370 +    }
 154.371 +
 154.372 +    /**
 154.373 +     * Complements the contents of this enum set.
 154.374 +     */
 154.375 +    abstract void complement();
 154.376 +
 154.377 +    /**
 154.378 +     * Throws an exception if e is not of the correct type for this enum set.
 154.379 +     */
 154.380 +    final void typeCheck(E e) {
 154.381 +        Class eClass = e.getClass();
 154.382 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 154.383 +            throw new ClassCastException(eClass + " != " + elementType);
 154.384 +    }
 154.385 +
 154.386 +    /**
 154.387 +     * Returns all of the values comprising E.
 154.388 +     * The result is uncloned, cached, and shared by all callers.
 154.389 +     */
 154.390 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
 154.391 +    private static native <E extends Enum<E>> E[] getUniverse(Class<E> elementType);
 154.392 +
 154.393 +    /**
 154.394 +     * This class is used to serialize all EnumSet instances, regardless of
 154.395 +     * implementation type.  It captures their "logical contents" and they
 154.396 +     * are reconstructed using public static factories.  This is necessary
 154.397 +     * to ensure that the existence of a particular implementation type is
 154.398 +     * an implementation detail.
 154.399 +     *
 154.400 +     * @serial include
 154.401 +     */
 154.402 +    private static class SerializationProxy <E extends Enum<E>>
 154.403 +        implements java.io.Serializable
 154.404 +    {
 154.405 +        /**
 154.406 +         * The element type of this enum set.
 154.407 +         *
 154.408 +         * @serial
 154.409 +         */
 154.410 +        private final Class<E> elementType;
 154.411 +
 154.412 +        /**
 154.413 +         * The elements contained in this enum set.
 154.414 +         *
 154.415 +         * @serial
 154.416 +         */
 154.417 +        private final Enum[] elements;
 154.418 +
 154.419 +        SerializationProxy(EnumSet<E> set) {
 154.420 +            elementType = set.elementType;
 154.421 +            elements = set.toArray(ZERO_LENGTH_ENUM_ARRAY);
 154.422 +        }
 154.423 +
 154.424 +        private Object readResolve() {
 154.425 +            EnumSet<E> result = EnumSet.noneOf(elementType);
 154.426 +            for (Enum e : elements)
 154.427 +                result.add((E)e);
 154.428 +            return result;
 154.429 +        }
 154.430 +
 154.431 +        private static final long serialVersionUID = 362491234563181265L;
 154.432 +    }
 154.433 +
 154.434 +    Object writeReplace() {
 154.435 +        return new SerializationProxy<>(this);
 154.436 +    }
 154.437 +
 154.438 +    // readObject method for the serialization proxy pattern
 154.439 +    // See Effective Java, Second Ed., Item 78.
 154.440 +    private void readObject(java.io.ObjectInputStream stream)
 154.441 +        throws java.io.InvalidObjectException {
 154.442 +        throw new java.io.InvalidObjectException("Proxy required");
 154.443 +    }
 154.444 +}
   155.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   155.2 +++ b/rt/emul/compact/src/main/java/java/util/IdentityHashMap.java	Mon Oct 07 14:20:58 2013 +0200
   155.3 @@ -0,0 +1,1243 @@
   155.4 +/*
   155.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   155.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   155.7 + *
   155.8 + * This code is free software; you can redistribute it and/or modify it
   155.9 + * under the terms of the GNU General Public License version 2 only, as
  155.10 + * published by the Free Software Foundation.  Oracle designates this
  155.11 + * particular file as subject to the "Classpath" exception as provided
  155.12 + * by Oracle in the LICENSE file that accompanied this code.
  155.13 + *
  155.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  155.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  155.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  155.17 + * version 2 for more details (a copy is included in the LICENSE file that
  155.18 + * accompanied this code).
  155.19 + *
  155.20 + * You should have received a copy of the GNU General Public License version
  155.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  155.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  155.23 + *
  155.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  155.25 + * or visit www.oracle.com if you need additional information or have any
  155.26 + * questions.
  155.27 + */
  155.28 +
  155.29 +package java.util;
  155.30 +import java.io.*;
  155.31 +
  155.32 +/**
  155.33 + * This class implements the <tt>Map</tt> interface with a hash table, using
  155.34 + * reference-equality in place of object-equality when comparing keys (and
  155.35 + * values).  In other words, in an <tt>IdentityHashMap</tt>, two keys
  155.36 + * <tt>k1</tt> and <tt>k2</tt> are considered equal if and only if
  155.37 + * <tt>(k1==k2)</tt>.  (In normal <tt>Map</tt> implementations (like
  155.38 + * <tt>HashMap</tt>) two keys <tt>k1</tt> and <tt>k2</tt> are considered equal
  155.39 + * if and only if <tt>(k1==null ? k2==null : k1.equals(k2))</tt>.)
  155.40 + *
  155.41 + * <p><b>This class is <i>not</i> a general-purpose <tt>Map</tt>
  155.42 + * implementation!  While this class implements the <tt>Map</tt> interface, it
  155.43 + * intentionally violates <tt>Map's</tt> general contract, which mandates the
  155.44 + * use of the <tt>equals</tt> method when comparing objects.  This class is
  155.45 + * designed for use only in the rare cases wherein reference-equality
  155.46 + * semantics are required.</b>
  155.47 + *
  155.48 + * <p>A typical use of this class is <i>topology-preserving object graph
  155.49 + * transformations</i>, such as serialization or deep-copying.  To perform such
  155.50 + * a transformation, a program must maintain a "node table" that keeps track
  155.51 + * of all the object references that have already been processed.  The node
  155.52 + * table must not equate distinct objects even if they happen to be equal.
  155.53 + * Another typical use of this class is to maintain <i>proxy objects</i>.  For
  155.54 + * example, a debugging facility might wish to maintain a proxy object for
  155.55 + * each object in the program being debugged.
  155.56 + *
  155.57 + * <p>This class provides all of the optional map operations, and permits
  155.58 + * <tt>null</tt> values and the <tt>null</tt> key.  This class makes no
  155.59 + * guarantees as to the order of the map; in particular, it does not guarantee
  155.60 + * that the order will remain constant over time.
  155.61 + *
  155.62 + * <p>This class provides constant-time performance for the basic
  155.63 + * operations (<tt>get</tt> and <tt>put</tt>), assuming the system
  155.64 + * identity hash function ({@link System#identityHashCode(Object)})
  155.65 + * disperses elements properly among the buckets.
  155.66 + *
  155.67 + * <p>This class has one tuning parameter (which affects performance but not
  155.68 + * semantics): <i>expected maximum size</i>.  This parameter is the maximum
  155.69 + * number of key-value mappings that the map is expected to hold.  Internally,
  155.70 + * this parameter is used to determine the number of buckets initially
  155.71 + * comprising the hash table.  The precise relationship between the expected
  155.72 + * maximum size and the number of buckets is unspecified.
  155.73 + *
  155.74 + * <p>If the size of the map (the number of key-value mappings) sufficiently
  155.75 + * exceeds the expected maximum size, the number of buckets is increased
  155.76 + * Increasing the number of buckets ("rehashing") may be fairly expensive, so
  155.77 + * it pays to create identity hash maps with a sufficiently large expected
  155.78 + * maximum size.  On the other hand, iteration over collection views requires
  155.79 + * time proportional to the number of buckets in the hash table, so it
  155.80 + * pays not to set the expected maximum size too high if you are especially
  155.81 + * concerned with iteration performance or memory usage.
  155.82 + *
  155.83 + * <p><strong>Note that this implementation is not synchronized.</strong>
  155.84 + * If multiple threads access an identity hash map concurrently, and at
  155.85 + * least one of the threads modifies the map structurally, it <i>must</i>
  155.86 + * be synchronized externally.  (A structural modification is any operation
  155.87 + * that adds or deletes one or more mappings; merely changing the value
  155.88 + * associated with a key that an instance already contains is not a
  155.89 + * structural modification.)  This is typically accomplished by
  155.90 + * synchronizing on some object that naturally encapsulates the map.
  155.91 + *
  155.92 + * If no such object exists, the map should be "wrapped" using the
  155.93 + * {@link Collections#synchronizedMap Collections.synchronizedMap}
  155.94 + * method.  This is best done at creation time, to prevent accidental
  155.95 + * unsynchronized access to the map:<pre>
  155.96 + *   Map m = Collections.synchronizedMap(new IdentityHashMap(...));</pre>
  155.97 + *
  155.98 + * <p>The iterators returned by the <tt>iterator</tt> method of the
  155.99 + * collections returned by all of this class's "collection view
 155.100 + * methods" are <i>fail-fast</i>: if the map is structurally modified
 155.101 + * at any time after the iterator is created, in any way except
 155.102 + * through the iterator's own <tt>remove</tt> method, the iterator
 155.103 + * will throw a {@link ConcurrentModificationException}.  Thus, in the
 155.104 + * face of concurrent modification, the iterator fails quickly and
 155.105 + * cleanly, rather than risking arbitrary, non-deterministic behavior
 155.106 + * at an undetermined time in the future.
 155.107 + *
 155.108 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 155.109 + * as it is, generally speaking, impossible to make any hard guarantees in the
 155.110 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 155.111 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 155.112 + * Therefore, it would be wrong to write a program that depended on this
 155.113 + * exception for its correctness: <i>fail-fast iterators should be used only
 155.114 + * to detect bugs.</i>
 155.115 + *
 155.116 + * <p>Implementation note: This is a simple <i>linear-probe</i> hash table,
 155.117 + * as described for example in texts by Sedgewick and Knuth.  The array
 155.118 + * alternates holding keys and values.  (This has better locality for large
 155.119 + * tables than does using separate arrays.)  For many JRE implementations
 155.120 + * and operation mixes, this class will yield better performance than
 155.121 + * {@link HashMap} (which uses <i>chaining</i> rather than linear-probing).
 155.122 + *
 155.123 + * <p>This class is a member of the
 155.124 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 155.125 + * Java Collections Framework</a>.
 155.126 + *
 155.127 + * @see     System#identityHashCode(Object)
 155.128 + * @see     Object#hashCode()
 155.129 + * @see     Collection
 155.130 + * @see     Map
 155.131 + * @see     HashMap
 155.132 + * @see     TreeMap
 155.133 + * @author  Doug Lea and Josh Bloch
 155.134 + * @since   1.4
 155.135 + */
 155.136 +
 155.137 +public class IdentityHashMap<K,V>
 155.138 +    extends AbstractMap<K,V>
 155.139 +    implements Map<K,V>, java.io.Serializable, Cloneable
 155.140 +{
 155.141 +    /**
 155.142 +     * The initial capacity used by the no-args constructor.
 155.143 +     * MUST be a power of two.  The value 32 corresponds to the
 155.144 +     * (specified) expected maximum size of 21, given a load factor
 155.145 +     * of 2/3.
 155.146 +     */
 155.147 +    private static final int DEFAULT_CAPACITY = 32;
 155.148 +
 155.149 +    /**
 155.150 +     * The minimum capacity, used if a lower value is implicitly specified
 155.151 +     * by either of the constructors with arguments.  The value 4 corresponds
 155.152 +     * to an expected maximum size of 2, given a load factor of 2/3.
 155.153 +     * MUST be a power of two.
 155.154 +     */
 155.155 +    private static final int MINIMUM_CAPACITY = 4;
 155.156 +
 155.157 +    /**
 155.158 +     * The maximum capacity, used if a higher value is implicitly specified
 155.159 +     * by either of the constructors with arguments.
 155.160 +     * MUST be a power of two <= 1<<29.
 155.161 +     */
 155.162 +    private static final int MAXIMUM_CAPACITY = 1 << 29;
 155.163 +
 155.164 +    /**
 155.165 +     * The table, resized as necessary. Length MUST always be a power of two.
 155.166 +     */
 155.167 +    private transient Object[] table;
 155.168 +
 155.169 +    /**
 155.170 +     * The number of key-value mappings contained in this identity hash map.
 155.171 +     *
 155.172 +     * @serial
 155.173 +     */
 155.174 +    private int size;
 155.175 +
 155.176 +    /**
 155.177 +     * The number of modifications, to support fast-fail iterators
 155.178 +     */
 155.179 +    private transient int modCount;
 155.180 +
 155.181 +    /**
 155.182 +     * The next size value at which to resize (capacity * load factor).
 155.183 +     */
 155.184 +    private transient int threshold;
 155.185 +
 155.186 +    /**
 155.187 +     * Value representing null keys inside tables.
 155.188 +     */
 155.189 +    private static final Object NULL_KEY = new Object();
 155.190 +
 155.191 +    /**
 155.192 +     * Use NULL_KEY for key if it is null.
 155.193 +     */
 155.194 +    private static Object maskNull(Object key) {
 155.195 +        return (key == null ? NULL_KEY : key);
 155.196 +    }
 155.197 +
 155.198 +    /**
 155.199 +     * Returns internal representation of null key back to caller as null.
 155.200 +     */
 155.201 +    private static Object unmaskNull(Object key) {
 155.202 +        return (key == NULL_KEY ? null : key);
 155.203 +    }
 155.204 +
 155.205 +    /**
 155.206 +     * Constructs a new, empty identity hash map with a default expected
 155.207 +     * maximum size (21).
 155.208 +     */
 155.209 +    public IdentityHashMap() {
 155.210 +        init(DEFAULT_CAPACITY);
 155.211 +    }
 155.212 +
 155.213 +    /**
 155.214 +     * Constructs a new, empty map with the specified expected maximum size.
 155.215 +     * Putting more than the expected number of key-value mappings into
 155.216 +     * the map may cause the internal data structure to grow, which may be
 155.217 +     * somewhat time-consuming.
 155.218 +     *
 155.219 +     * @param expectedMaxSize the expected maximum size of the map
 155.220 +     * @throws IllegalArgumentException if <tt>expectedMaxSize</tt> is negative
 155.221 +     */
 155.222 +    public IdentityHashMap(int expectedMaxSize) {
 155.223 +        if (expectedMaxSize < 0)
 155.224 +            throw new IllegalArgumentException("expectedMaxSize is negative: "
 155.225 +                                               + expectedMaxSize);
 155.226 +        init(capacity(expectedMaxSize));
 155.227 +    }
 155.228 +
 155.229 +    /**
 155.230 +     * Returns the appropriate capacity for the specified expected maximum
 155.231 +     * size.  Returns the smallest power of two between MINIMUM_CAPACITY
 155.232 +     * and MAXIMUM_CAPACITY, inclusive, that is greater than
 155.233 +     * (3 * expectedMaxSize)/2, if such a number exists.  Otherwise
 155.234 +     * returns MAXIMUM_CAPACITY.  If (3 * expectedMaxSize)/2 is negative, it
 155.235 +     * is assumed that overflow has occurred, and MAXIMUM_CAPACITY is returned.
 155.236 +     */
 155.237 +    private int capacity(int expectedMaxSize) {
 155.238 +        // Compute min capacity for expectedMaxSize given a load factor of 2/3
 155.239 +        int minCapacity = (3 * expectedMaxSize)/2;
 155.240 +
 155.241 +        // Compute the appropriate capacity
 155.242 +        int result;
 155.243 +        if (minCapacity > MAXIMUM_CAPACITY || minCapacity < 0) {
 155.244 +            result = MAXIMUM_CAPACITY;
 155.245 +        } else {
 155.246 +            result = MINIMUM_CAPACITY;
 155.247 +            while (result < minCapacity)
 155.248 +                result <<= 1;
 155.249 +        }
 155.250 +        return result;
 155.251 +    }
 155.252 +
 155.253 +    /**
 155.254 +     * Initializes object to be an empty map with the specified initial
 155.255 +     * capacity, which is assumed to be a power of two between
 155.256 +     * MINIMUM_CAPACITY and MAXIMUM_CAPACITY inclusive.
 155.257 +     */
 155.258 +    private void init(int initCapacity) {
 155.259 +        // assert (initCapacity & -initCapacity) == initCapacity; // power of 2
 155.260 +        // assert initCapacity >= MINIMUM_CAPACITY;
 155.261 +        // assert initCapacity <= MAXIMUM_CAPACITY;
 155.262 +
 155.263 +        threshold = (initCapacity * 2)/3;
 155.264 +        table = new Object[2 * initCapacity];
 155.265 +    }
 155.266 +
 155.267 +    /**
 155.268 +     * Constructs a new identity hash map containing the keys-value mappings
 155.269 +     * in the specified map.
 155.270 +     *
 155.271 +     * @param m the map whose mappings are to be placed into this map
 155.272 +     * @throws NullPointerException if the specified map is null
 155.273 +     */
 155.274 +    public IdentityHashMap(Map<? extends K, ? extends V> m) {
 155.275 +        // Allow for a bit of growth
 155.276 +        this((int) ((1 + m.size()) * 1.1));
 155.277 +        putAll(m);
 155.278 +    }
 155.279 +
 155.280 +    /**
 155.281 +     * Returns the number of key-value mappings in this identity hash map.
 155.282 +     *
 155.283 +     * @return the number of key-value mappings in this map
 155.284 +     */
 155.285 +    public int size() {
 155.286 +        return size;
 155.287 +    }
 155.288 +
 155.289 +    /**
 155.290 +     * Returns <tt>true</tt> if this identity hash map contains no key-value
 155.291 +     * mappings.
 155.292 +     *
 155.293 +     * @return <tt>true</tt> if this identity hash map contains no key-value
 155.294 +     *         mappings
 155.295 +     */
 155.296 +    public boolean isEmpty() {
 155.297 +        return size == 0;
 155.298 +    }
 155.299 +
 155.300 +    /**
 155.301 +     * Returns index for Object x.
 155.302 +     */
 155.303 +    private static int hash(Object x, int length) {
 155.304 +        int h = System.identityHashCode(x);
 155.305 +        // Multiply by -127, and left-shift to use least bit as part of hash
 155.306 +        return ((h << 1) - (h << 8)) & (length - 1);
 155.307 +    }
 155.308 +
 155.309 +    /**
 155.310 +     * Circularly traverses table of size len.
 155.311 +     */
 155.312 +    private static int nextKeyIndex(int i, int len) {
 155.313 +        return (i + 2 < len ? i + 2 : 0);
 155.314 +    }
 155.315 +
 155.316 +    /**
 155.317 +     * Returns the value to which the specified key is mapped,
 155.318 +     * or {@code null} if this map contains no mapping for the key.
 155.319 +     *
 155.320 +     * <p>More formally, if this map contains a mapping from a key
 155.321 +     * {@code k} to a value {@code v} such that {@code (key == k)},
 155.322 +     * then this method returns {@code v}; otherwise it returns
 155.323 +     * {@code null}.  (There can be at most one such mapping.)
 155.324 +     *
 155.325 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 155.326 +     * indicate that the map contains no mapping for the key; it's also
 155.327 +     * possible that the map explicitly maps the key to {@code null}.
 155.328 +     * The {@link #containsKey containsKey} operation may be used to
 155.329 +     * distinguish these two cases.
 155.330 +     *
 155.331 +     * @see #put(Object, Object)
 155.332 +     */
 155.333 +    public V get(Object key) {
 155.334 +        Object k = maskNull(key);
 155.335 +        Object[] tab = table;
 155.336 +        int len = tab.length;
 155.337 +        int i = hash(k, len);
 155.338 +        while (true) {
 155.339 +            Object item = tab[i];
 155.340 +            if (item == k)
 155.341 +                return (V) tab[i + 1];
 155.342 +            if (item == null)
 155.343 +                return null;
 155.344 +            i = nextKeyIndex(i, len);
 155.345 +        }
 155.346 +    }
 155.347 +
 155.348 +    /**
 155.349 +     * Tests whether the specified object reference is a key in this identity
 155.350 +     * hash map.
 155.351 +     *
 155.352 +     * @param   key   possible key
 155.353 +     * @return  <code>true</code> if the specified object reference is a key
 155.354 +     *          in this map
 155.355 +     * @see     #containsValue(Object)
 155.356 +     */
 155.357 +    public boolean containsKey(Object key) {
 155.358 +        Object k = maskNull(key);
 155.359 +        Object[] tab = table;
 155.360 +        int len = tab.length;
 155.361 +        int i = hash(k, len);
 155.362 +        while (true) {
 155.363 +            Object item = tab[i];
 155.364 +            if (item == k)
 155.365 +                return true;
 155.366 +            if (item == null)
 155.367 +                return false;
 155.368 +            i = nextKeyIndex(i, len);
 155.369 +        }
 155.370 +    }
 155.371 +
 155.372 +    /**
 155.373 +     * Tests whether the specified object reference is a value in this identity
 155.374 +     * hash map.
 155.375 +     *
 155.376 +     * @param value value whose presence in this map is to be tested
 155.377 +     * @return <tt>true</tt> if this map maps one or more keys to the
 155.378 +     *         specified object reference
 155.379 +     * @see     #containsKey(Object)
 155.380 +     */
 155.381 +    public boolean containsValue(Object value) {
 155.382 +        Object[] tab = table;
 155.383 +        for (int i = 1; i < tab.length; i += 2)
 155.384 +            if (tab[i] == value && tab[i - 1] != null)
 155.385 +                return true;
 155.386 +
 155.387 +        return false;
 155.388 +    }
 155.389 +
 155.390 +    /**
 155.391 +     * Tests if the specified key-value mapping is in the map.
 155.392 +     *
 155.393 +     * @param   key   possible key
 155.394 +     * @param   value possible value
 155.395 +     * @return  <code>true</code> if and only if the specified key-value
 155.396 +     *          mapping is in the map
 155.397 +     */
 155.398 +    private boolean containsMapping(Object key, Object value) {
 155.399 +        Object k = maskNull(key);
 155.400 +        Object[] tab = table;
 155.401 +        int len = tab.length;
 155.402 +        int i = hash(k, len);
 155.403 +        while (true) {
 155.404 +            Object item = tab[i];
 155.405 +            if (item == k)
 155.406 +                return tab[i + 1] == value;
 155.407 +            if (item == null)
 155.408 +                return false;
 155.409 +            i = nextKeyIndex(i, len);
 155.410 +        }
 155.411 +    }
 155.412 +
 155.413 +    /**
 155.414 +     * Associates the specified value with the specified key in this identity
 155.415 +     * hash map.  If the map previously contained a mapping for the key, the
 155.416 +     * old value is replaced.
 155.417 +     *
 155.418 +     * @param key the key with which the specified value is to be associated
 155.419 +     * @param value the value to be associated with the specified key
 155.420 +     * @return the previous value associated with <tt>key</tt>, or
 155.421 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 155.422 +     *         (A <tt>null</tt> return can also indicate that the map
 155.423 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 155.424 +     * @see     Object#equals(Object)
 155.425 +     * @see     #get(Object)
 155.426 +     * @see     #containsKey(Object)
 155.427 +     */
 155.428 +    public V put(K key, V value) {
 155.429 +        Object k = maskNull(key);
 155.430 +        Object[] tab = table;
 155.431 +        int len = tab.length;
 155.432 +        int i = hash(k, len);
 155.433 +
 155.434 +        Object item;
 155.435 +        while ( (item = tab[i]) != null) {
 155.436 +            if (item == k) {
 155.437 +                V oldValue = (V) tab[i + 1];
 155.438 +                tab[i + 1] = value;
 155.439 +                return oldValue;
 155.440 +            }
 155.441 +            i = nextKeyIndex(i, len);
 155.442 +        }
 155.443 +
 155.444 +        modCount++;
 155.445 +        tab[i] = k;
 155.446 +        tab[i + 1] = value;
 155.447 +        if (++size >= threshold)
 155.448 +            resize(len); // len == 2 * current capacity.
 155.449 +        return null;
 155.450 +    }
 155.451 +
 155.452 +    /**
 155.453 +     * Resize the table to hold given capacity.
 155.454 +     *
 155.455 +     * @param newCapacity the new capacity, must be a power of two.
 155.456 +     */
 155.457 +    private void resize(int newCapacity) {
 155.458 +        // assert (newCapacity & -newCapacity) == newCapacity; // power of 2
 155.459 +        int newLength = newCapacity * 2;
 155.460 +
 155.461 +        Object[] oldTable = table;
 155.462 +        int oldLength = oldTable.length;
 155.463 +        if (oldLength == 2*MAXIMUM_CAPACITY) { // can't expand any further
 155.464 +            if (threshold == MAXIMUM_CAPACITY-1)
 155.465 +                throw new IllegalStateException("Capacity exhausted.");
 155.466 +            threshold = MAXIMUM_CAPACITY-1;  // Gigantic map!
 155.467 +            return;
 155.468 +        }
 155.469 +        if (oldLength >= newLength)
 155.470 +            return;
 155.471 +
 155.472 +        Object[] newTable = new Object[newLength];
 155.473 +        threshold = newLength / 3;
 155.474 +
 155.475 +        for (int j = 0; j < oldLength; j += 2) {
 155.476 +            Object key = oldTable[j];
 155.477 +            if (key != null) {
 155.478 +                Object value = oldTable[j+1];
 155.479 +                oldTable[j] = null;
 155.480 +                oldTable[j+1] = null;
 155.481 +                int i = hash(key, newLength);
 155.482 +                while (newTable[i] != null)
 155.483 +                    i = nextKeyIndex(i, newLength);
 155.484 +                newTable[i] = key;
 155.485 +                newTable[i + 1] = value;
 155.486 +            }
 155.487 +        }
 155.488 +        table = newTable;
 155.489 +    }
 155.490 +
 155.491 +    /**
 155.492 +     * Copies all of the mappings from the specified map to this map.
 155.493 +     * These mappings will replace any mappings that this map had for
 155.494 +     * any of the keys currently in the specified map.
 155.495 +     *
 155.496 +     * @param m mappings to be stored in this map
 155.497 +     * @throws NullPointerException if the specified map is null
 155.498 +     */
 155.499 +    public void putAll(Map<? extends K, ? extends V> m) {
 155.500 +        int n = m.size();
 155.501 +        if (n == 0)
 155.502 +            return;
 155.503 +        if (n > threshold) // conservatively pre-expand
 155.504 +            resize(capacity(n));
 155.505 +
 155.506 +        for (Entry<? extends K, ? extends V> e : m.entrySet())
 155.507 +            put(e.getKey(), e.getValue());
 155.508 +    }
 155.509 +
 155.510 +    /**
 155.511 +     * Removes the mapping for this key from this map if present.
 155.512 +     *
 155.513 +     * @param key key whose mapping is to be removed from the map
 155.514 +     * @return the previous value associated with <tt>key</tt>, or
 155.515 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 155.516 +     *         (A <tt>null</tt> return can also indicate that the map
 155.517 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 155.518 +     */
 155.519 +    public V remove(Object key) {
 155.520 +        Object k = maskNull(key);
 155.521 +        Object[] tab = table;
 155.522 +        int len = tab.length;
 155.523 +        int i = hash(k, len);
 155.524 +
 155.525 +        while (true) {
 155.526 +            Object item = tab[i];
 155.527 +            if (item == k) {
 155.528 +                modCount++;
 155.529 +                size--;
 155.530 +                V oldValue = (V) tab[i + 1];
 155.531 +                tab[i + 1] = null;
 155.532 +                tab[i] = null;
 155.533 +                closeDeletion(i);
 155.534 +                return oldValue;
 155.535 +            }
 155.536 +            if (item == null)
 155.537 +                return null;
 155.538 +            i = nextKeyIndex(i, len);
 155.539 +        }
 155.540 +
 155.541 +    }
 155.542 +
 155.543 +    /**
 155.544 +     * Removes the specified key-value mapping from the map if it is present.
 155.545 +     *
 155.546 +     * @param   key   possible key
 155.547 +     * @param   value possible value
 155.548 +     * @return  <code>true</code> if and only if the specified key-value
 155.549 +     *          mapping was in the map
 155.550 +     */
 155.551 +    private boolean removeMapping(Object key, Object value) {
 155.552 +        Object k = maskNull(key);
 155.553 +        Object[] tab = table;
 155.554 +        int len = tab.length;
 155.555 +        int i = hash(k, len);
 155.556 +
 155.557 +        while (true) {
 155.558 +            Object item = tab[i];
 155.559 +            if (item == k) {
 155.560 +                if (tab[i + 1] != value)
 155.561 +                    return false;
 155.562 +                modCount++;
 155.563 +                size--;
 155.564 +                tab[i] = null;
 155.565 +                tab[i + 1] = null;
 155.566 +                closeDeletion(i);
 155.567 +                return true;
 155.568 +            }
 155.569 +            if (item == null)
 155.570 +                return false;
 155.571 +            i = nextKeyIndex(i, len);
 155.572 +        }
 155.573 +    }
 155.574 +
 155.575 +    /**
 155.576 +     * Rehash all possibly-colliding entries following a
 155.577 +     * deletion. This preserves the linear-probe
 155.578 +     * collision properties required by get, put, etc.
 155.579 +     *
 155.580 +     * @param d the index of a newly empty deleted slot
 155.581 +     */
 155.582 +    private void closeDeletion(int d) {
 155.583 +        // Adapted from Knuth Section 6.4 Algorithm R
 155.584 +        Object[] tab = table;
 155.585 +        int len = tab.length;
 155.586 +
 155.587 +        // Look for items to swap into newly vacated slot
 155.588 +        // starting at index immediately following deletion,
 155.589 +        // and continuing until a null slot is seen, indicating
 155.590 +        // the end of a run of possibly-colliding keys.
 155.591 +        Object item;
 155.592 +        for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
 155.593 +             i = nextKeyIndex(i, len) ) {
 155.594 +            // The following test triggers if the item at slot i (which
 155.595 +            // hashes to be at slot r) should take the spot vacated by d.
 155.596 +            // If so, we swap it in, and then continue with d now at the
 155.597 +            // newly vacated i.  This process will terminate when we hit
 155.598 +            // the null slot at the end of this run.
 155.599 +            // The test is messy because we are using a circular table.
 155.600 +            int r = hash(item, len);
 155.601 +            if ((i < r && (r <= d || d <= i)) || (r <= d && d <= i)) {
 155.602 +                tab[d] = item;
 155.603 +                tab[d + 1] = tab[i + 1];
 155.604 +                tab[i] = null;
 155.605 +                tab[i + 1] = null;
 155.606 +                d = i;
 155.607 +            }
 155.608 +        }
 155.609 +    }
 155.610 +
 155.611 +    /**
 155.612 +     * Removes all of the mappings from this map.
 155.613 +     * The map will be empty after this call returns.
 155.614 +     */
 155.615 +    public void clear() {
 155.616 +        modCount++;
 155.617 +        Object[] tab = table;
 155.618 +        for (int i = 0; i < tab.length; i++)
 155.619 +            tab[i] = null;
 155.620 +        size = 0;
 155.621 +    }
 155.622 +
 155.623 +    /**
 155.624 +     * Compares the specified object with this map for equality.  Returns
 155.625 +     * <tt>true</tt> if the given object is also a map and the two maps
 155.626 +     * represent identical object-reference mappings.  More formally, this
 155.627 +     * map is equal to another map <tt>m</tt> if and only if
 155.628 +     * <tt>this.entrySet().equals(m.entrySet())</tt>.
 155.629 +     *
 155.630 +     * <p><b>Owing to the reference-equality-based semantics of this map it is
 155.631 +     * possible that the symmetry and transitivity requirements of the
 155.632 +     * <tt>Object.equals</tt> contract may be violated if this map is compared
 155.633 +     * to a normal map.  However, the <tt>Object.equals</tt> contract is
 155.634 +     * guaranteed to hold among <tt>IdentityHashMap</tt> instances.</b>
 155.635 +     *
 155.636 +     * @param  o object to be compared for equality with this map
 155.637 +     * @return <tt>true</tt> if the specified object is equal to this map
 155.638 +     * @see Object#equals(Object)
 155.639 +     */
 155.640 +    public boolean equals(Object o) {
 155.641 +        if (o == this) {
 155.642 +            return true;
 155.643 +        } else if (o instanceof IdentityHashMap) {
 155.644 +            IdentityHashMap m = (IdentityHashMap) o;
 155.645 +            if (m.size() != size)
 155.646 +                return false;
 155.647 +
 155.648 +            Object[] tab = m.table;
 155.649 +            for (int i = 0; i < tab.length; i+=2) {
 155.650 +                Object k = tab[i];
 155.651 +                if (k != null && !containsMapping(k, tab[i + 1]))
 155.652 +                    return false;
 155.653 +            }
 155.654 +            return true;
 155.655 +        } else if (o instanceof Map) {
 155.656 +            Map m = (Map)o;
 155.657 +            return entrySet().equals(m.entrySet());
 155.658 +        } else {
 155.659 +            return false;  // o is not a Map
 155.660 +        }
 155.661 +    }
 155.662 +
 155.663 +    /**
 155.664 +     * Returns the hash code value for this map.  The hash code of a map is
 155.665 +     * defined to be the sum of the hash codes of each entry in the map's
 155.666 +     * <tt>entrySet()</tt> view.  This ensures that <tt>m1.equals(m2)</tt>
 155.667 +     * implies that <tt>m1.hashCode()==m2.hashCode()</tt> for any two
 155.668 +     * <tt>IdentityHashMap</tt> instances <tt>m1</tt> and <tt>m2</tt>, as
 155.669 +     * required by the general contract of {@link Object#hashCode}.
 155.670 +     *
 155.671 +     * <p><b>Owing to the reference-equality-based semantics of the
 155.672 +     * <tt>Map.Entry</tt> instances in the set returned by this map's
 155.673 +     * <tt>entrySet</tt> method, it is possible that the contractual
 155.674 +     * requirement of <tt>Object.hashCode</tt> mentioned in the previous
 155.675 +     * paragraph will be violated if one of the two objects being compared is
 155.676 +     * an <tt>IdentityHashMap</tt> instance and the other is a normal map.</b>
 155.677 +     *
 155.678 +     * @return the hash code value for this map
 155.679 +     * @see Object#equals(Object)
 155.680 +     * @see #equals(Object)
 155.681 +     */
 155.682 +    public int hashCode() {
 155.683 +        int result = 0;
 155.684 +        Object[] tab = table;
 155.685 +        for (int i = 0; i < tab.length; i +=2) {
 155.686 +            Object key = tab[i];
 155.687 +            if (key != null) {
 155.688 +                Object k = unmaskNull(key);
 155.689 +                result += System.identityHashCode(k) ^
 155.690 +                          System.identityHashCode(tab[i + 1]);
 155.691 +            }
 155.692 +        }
 155.693 +        return result;
 155.694 +    }
 155.695 +
 155.696 +    /**
 155.697 +     * Returns a shallow copy of this identity hash map: the keys and values
 155.698 +     * themselves are not cloned.
 155.699 +     *
 155.700 +     * @return a shallow copy of this map
 155.701 +     */
 155.702 +    public Object clone() {
 155.703 +        try {
 155.704 +            IdentityHashMap<K,V> m = (IdentityHashMap<K,V>) super.clone();
 155.705 +            m.entrySet = null;
 155.706 +            m.table = table.clone();
 155.707 +            return m;
 155.708 +        } catch (CloneNotSupportedException e) {
 155.709 +            throw new InternalError();
 155.710 +        }
 155.711 +    }
 155.712 +
 155.713 +    private abstract class IdentityHashMapIterator<T> implements Iterator<T> {
 155.714 +        int index = (size != 0 ? 0 : table.length); // current slot.
 155.715 +        int expectedModCount = modCount; // to support fast-fail
 155.716 +        int lastReturnedIndex = -1;      // to allow remove()
 155.717 +        boolean indexValid; // To avoid unnecessary next computation
 155.718 +        Object[] traversalTable = table; // reference to main table or copy
 155.719 +
 155.720 +        public boolean hasNext() {
 155.721 +            Object[] tab = traversalTable;
 155.722 +            for (int i = index; i < tab.length; i+=2) {
 155.723 +                Object key = tab[i];
 155.724 +                if (key != null) {
 155.725 +                    index = i;
 155.726 +                    return indexValid = true;
 155.727 +                }
 155.728 +            }
 155.729 +            index = tab.length;
 155.730 +            return false;
 155.731 +        }
 155.732 +
 155.733 +        protected int nextIndex() {
 155.734 +            if (modCount != expectedModCount)
 155.735 +                throw new ConcurrentModificationException();
 155.736 +            if (!indexValid && !hasNext())
 155.737 +                throw new NoSuchElementException();
 155.738 +
 155.739 +            indexValid = false;
 155.740 +            lastReturnedIndex = index;
 155.741 +            index += 2;
 155.742 +            return lastReturnedIndex;
 155.743 +        }
 155.744 +
 155.745 +        public void remove() {
 155.746 +            if (lastReturnedIndex == -1)
 155.747 +                throw new IllegalStateException();
 155.748 +            if (modCount != expectedModCount)
 155.749 +                throw new ConcurrentModificationException();
 155.750 +
 155.751 +            expectedModCount = ++modCount;
 155.752 +            int deletedSlot = lastReturnedIndex;
 155.753 +            lastReturnedIndex = -1;
 155.754 +            // back up index to revisit new contents after deletion
 155.755 +            index = deletedSlot;
 155.756 +            indexValid = false;
 155.757 +
 155.758 +            // Removal code proceeds as in closeDeletion except that
 155.759 +            // it must catch the rare case where an element already
 155.760 +            // seen is swapped into a vacant slot that will be later
 155.761 +            // traversed by this iterator. We cannot allow future
 155.762 +            // next() calls to return it again.  The likelihood of
 155.763 +            // this occurring under 2/3 load factor is very slim, but
 155.764 +            // when it does happen, we must make a copy of the rest of
 155.765 +            // the table to use for the rest of the traversal. Since
 155.766 +            // this can only happen when we are near the end of the table,
 155.767 +            // even in these rare cases, this is not very expensive in
 155.768 +            // time or space.
 155.769 +
 155.770 +            Object[] tab = traversalTable;
 155.771 +            int len = tab.length;
 155.772 +
 155.773 +            int d = deletedSlot;
 155.774 +            K key = (K) tab[d];
 155.775 +            tab[d] = null;        // vacate the slot
 155.776 +            tab[d + 1] = null;
 155.777 +
 155.778 +            // If traversing a copy, remove in real table.
 155.779 +            // We can skip gap-closure on copy.
 155.780 +            if (tab != IdentityHashMap.this.table) {
 155.781 +                IdentityHashMap.this.remove(key);
 155.782 +                expectedModCount = modCount;
 155.783 +                return;
 155.784 +            }
 155.785 +
 155.786 +            size--;
 155.787 +
 155.788 +            Object item;
 155.789 +            for (int i = nextKeyIndex(d, len); (item = tab[i]) != null;
 155.790 +                 i = nextKeyIndex(i, len)) {
 155.791 +                int r = hash(item, len);
 155.792 +                // See closeDeletion for explanation of this conditional
 155.793 +                if ((i < r && (r <= d || d <= i)) ||
 155.794 +                    (r <= d && d <= i)) {
 155.795 +
 155.796 +                    // If we are about to swap an already-seen element
 155.797 +                    // into a slot that may later be returned by next(),
 155.798 +                    // then clone the rest of table for use in future
 155.799 +                    // next() calls. It is OK that our copy will have
 155.800 +                    // a gap in the "wrong" place, since it will never
 155.801 +                    // be used for searching anyway.
 155.802 +
 155.803 +                    if (i < deletedSlot && d >= deletedSlot &&
 155.804 +                        traversalTable == IdentityHashMap.this.table) {
 155.805 +                        int remaining = len - deletedSlot;
 155.806 +                        Object[] newTable = new Object[remaining];
 155.807 +                        System.arraycopy(tab, deletedSlot,
 155.808 +                                         newTable, 0, remaining);
 155.809 +                        traversalTable = newTable;
 155.810 +                        index = 0;
 155.811 +                    }
 155.812 +
 155.813 +                    tab[d] = item;
 155.814 +                    tab[d + 1] = tab[i + 1];
 155.815 +                    tab[i] = null;
 155.816 +                    tab[i + 1] = null;
 155.817 +                    d = i;
 155.818 +                }
 155.819 +            }
 155.820 +        }
 155.821 +    }
 155.822 +
 155.823 +    private class KeyIterator extends IdentityHashMapIterator<K> {
 155.824 +        public K next() {
 155.825 +            return (K) unmaskNull(traversalTable[nextIndex()]);
 155.826 +        }
 155.827 +    }
 155.828 +
 155.829 +    private class ValueIterator extends IdentityHashMapIterator<V> {
 155.830 +        public V next() {
 155.831 +            return (V) traversalTable[nextIndex() + 1];
 155.832 +        }
 155.833 +    }
 155.834 +
 155.835 +    private class EntryIterator
 155.836 +        extends IdentityHashMapIterator<Map.Entry<K,V>>
 155.837 +    {
 155.838 +        private Entry lastReturnedEntry = null;
 155.839 +
 155.840 +        public Map.Entry<K,V> next() {
 155.841 +            lastReturnedEntry = new Entry(nextIndex());
 155.842 +            return lastReturnedEntry;
 155.843 +        }
 155.844 +
 155.845 +        public void remove() {
 155.846 +            lastReturnedIndex =
 155.847 +                ((null == lastReturnedEntry) ? -1 : lastReturnedEntry.index);
 155.848 +            super.remove();
 155.849 +            lastReturnedEntry.index = lastReturnedIndex;
 155.850 +            lastReturnedEntry = null;
 155.851 +        }
 155.852 +
 155.853 +        private class Entry implements Map.Entry<K,V> {
 155.854 +            private int index;
 155.855 +
 155.856 +            private Entry(int index) {
 155.857 +                this.index = index;
 155.858 +            }
 155.859 +
 155.860 +            public K getKey() {
 155.861 +                checkIndexForEntryUse();
 155.862 +                return (K) unmaskNull(traversalTable[index]);
 155.863 +            }
 155.864 +
 155.865 +            public V getValue() {
 155.866 +                checkIndexForEntryUse();
 155.867 +                return (V) traversalTable[index+1];
 155.868 +            }
 155.869 +
 155.870 +            public V setValue(V value) {
 155.871 +                checkIndexForEntryUse();
 155.872 +                V oldValue = (V) traversalTable[index+1];
 155.873 +                traversalTable[index+1] = value;
 155.874 +                // if shadowing, force into main table
 155.875 +                if (traversalTable != IdentityHashMap.this.table)
 155.876 +                    put((K) traversalTable[index], value);
 155.877 +                return oldValue;
 155.878 +            }
 155.879 +
 155.880 +            public boolean equals(Object o) {
 155.881 +                if (index < 0)
 155.882 +                    return super.equals(o);
 155.883 +
 155.884 +                if (!(o instanceof Map.Entry))
 155.885 +                    return false;
 155.886 +                Map.Entry e = (Map.Entry)o;
 155.887 +                return (e.getKey() == unmaskNull(traversalTable[index]) &&
 155.888 +                       e.getValue() == traversalTable[index+1]);
 155.889 +            }
 155.890 +
 155.891 +            public int hashCode() {
 155.892 +                if (lastReturnedIndex < 0)
 155.893 +                    return super.hashCode();
 155.894 +
 155.895 +                return (System.identityHashCode(unmaskNull(traversalTable[index])) ^
 155.896 +                       System.identityHashCode(traversalTable[index+1]));
 155.897 +            }
 155.898 +
 155.899 +            public String toString() {
 155.900 +                if (index < 0)
 155.901 +                    return super.toString();
 155.902 +
 155.903 +                return (unmaskNull(traversalTable[index]) + "="
 155.904 +                        + traversalTable[index+1]);
 155.905 +            }
 155.906 +
 155.907 +            private void checkIndexForEntryUse() {
 155.908 +                if (index < 0)
 155.909 +                    throw new IllegalStateException("Entry was removed");
 155.910 +            }
 155.911 +        }
 155.912 +    }
 155.913 +
 155.914 +    // Views
 155.915 +
 155.916 +    /**
 155.917 +     * This field is initialized to contain an instance of the entry set
 155.918 +     * view the first time this view is requested.  The view is stateless,
 155.919 +     * so there's no reason to create more than one.
 155.920 +     */
 155.921 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 155.922 +
 155.923 +    /**
 155.924 +     * Returns an identity-based set view of the keys contained in this map.
 155.925 +     * The set is backed by the map, so changes to the map are reflected in
 155.926 +     * the set, and vice-versa.  If the map is modified while an iteration
 155.927 +     * over the set is in progress, the results of the iteration are
 155.928 +     * undefined.  The set supports element removal, which removes the
 155.929 +     * corresponding mapping from the map, via the <tt>Iterator.remove</tt>,
 155.930 +     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt>, and
 155.931 +     * <tt>clear</tt> methods.  It does not support the <tt>add</tt> or
 155.932 +     * <tt>addAll</tt> methods.
 155.933 +     *
 155.934 +     * <p><b>While the object returned by this method implements the
 155.935 +     * <tt>Set</tt> interface, it does <i>not</i> obey <tt>Set's</tt> general
 155.936 +     * contract.  Like its backing map, the set returned by this method
 155.937 +     * defines element equality as reference-equality rather than
 155.938 +     * object-equality.  This affects the behavior of its <tt>contains</tt>,
 155.939 +     * <tt>remove</tt>, <tt>containsAll</tt>, <tt>equals</tt>, and
 155.940 +     * <tt>hashCode</tt> methods.</b>
 155.941 +     *
 155.942 +     * <p><b>The <tt>equals</tt> method of the returned set returns <tt>true</tt>
 155.943 +     * only if the specified object is a set containing exactly the same
 155.944 +     * object references as the returned set.  The symmetry and transitivity
 155.945 +     * requirements of the <tt>Object.equals</tt> contract may be violated if
 155.946 +     * the set returned by this method is compared to a normal set.  However,
 155.947 +     * the <tt>Object.equals</tt> contract is guaranteed to hold among sets
 155.948 +     * returned by this method.</b>
 155.949 +     *
 155.950 +     * <p>The <tt>hashCode</tt> method of the returned set returns the sum of
 155.951 +     * the <i>identity hashcodes</i> of the elements in the set, rather than
 155.952 +     * the sum of their hashcodes.  This is mandated by the change in the
 155.953 +     * semantics of the <tt>equals</tt> method, in order to enforce the
 155.954 +     * general contract of the <tt>Object.hashCode</tt> method among sets
 155.955 +     * returned by this method.
 155.956 +     *
 155.957 +     * @return an identity-based set view of the keys contained in this map
 155.958 +     * @see Object#equals(Object)
 155.959 +     * @see System#identityHashCode(Object)
 155.960 +     */
 155.961 +    public Set<K> keySet() {
 155.962 +        Set<K> ks = keySet;
 155.963 +        if (ks != null)
 155.964 +            return ks;
 155.965 +        else
 155.966 +            return keySet = new KeySet();
 155.967 +    }
 155.968 +
 155.969 +    private class KeySet extends AbstractSet<K> {
 155.970 +        public Iterator<K> iterator() {
 155.971 +            return new KeyIterator();
 155.972 +        }
 155.973 +        public int size() {
 155.974 +            return size;
 155.975 +        }
 155.976 +        public boolean contains(Object o) {
 155.977 +            return containsKey(o);
 155.978 +        }
 155.979 +        public boolean remove(Object o) {
 155.980 +            int oldSize = size;
 155.981 +            IdentityHashMap.this.remove(o);
 155.982 +            return size != oldSize;
 155.983 +        }
 155.984 +        /*
 155.985 +         * Must revert from AbstractSet's impl to AbstractCollection's, as
 155.986 +         * the former contains an optimization that results in incorrect
 155.987 +         * behavior when c is a smaller "normal" (non-identity-based) Set.
 155.988 +         */
 155.989 +        public boolean removeAll(Collection<?> c) {
 155.990 +            boolean modified = false;
 155.991 +            for (Iterator<K> i = iterator(); i.hasNext(); ) {
 155.992 +                if (c.contains(i.next())) {
 155.993 +                    i.remove();
 155.994 +                    modified = true;
 155.995 +                }
 155.996 +            }
 155.997 +            return modified;
 155.998 +        }
 155.999 +        public void clear() {
155.1000 +            IdentityHashMap.this.clear();
155.1001 +        }
155.1002 +        public int hashCode() {
155.1003 +            int result = 0;
155.1004 +            for (K key : this)
155.1005 +                result += System.identityHashCode(key);
155.1006 +            return result;
155.1007 +        }
155.1008 +    }
155.1009 +
155.1010 +    /**
155.1011 +     * Returns a {@link Collection} view of the values contained in this map.
155.1012 +     * The collection is backed by the map, so changes to the map are
155.1013 +     * reflected in the collection, and vice-versa.  If the map is
155.1014 +     * modified while an iteration over the collection is in progress,
155.1015 +     * the results of the iteration are undefined.  The collection
155.1016 +     * supports element removal, which removes the corresponding
155.1017 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
155.1018 +     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
155.1019 +     * <tt>retainAll</tt> and <tt>clear</tt> methods.  It does not
155.1020 +     * support the <tt>add</tt> or <tt>addAll</tt> methods.
155.1021 +     *
155.1022 +     * <p><b>While the object returned by this method implements the
155.1023 +     * <tt>Collection</tt> interface, it does <i>not</i> obey
155.1024 +     * <tt>Collection's</tt> general contract.  Like its backing map,
155.1025 +     * the collection returned by this method defines element equality as
155.1026 +     * reference-equality rather than object-equality.  This affects the
155.1027 +     * behavior of its <tt>contains</tt>, <tt>remove</tt> and
155.1028 +     * <tt>containsAll</tt> methods.</b>
155.1029 +     */
155.1030 +    public Collection<V> values() {
155.1031 +        Collection<V> vs = values;
155.1032 +        if (vs != null)
155.1033 +            return vs;
155.1034 +        else
155.1035 +            return values = new Values();
155.1036 +    }
155.1037 +
155.1038 +    private class Values extends AbstractCollection<V> {
155.1039 +        public Iterator<V> iterator() {
155.1040 +            return new ValueIterator();
155.1041 +        }
155.1042 +        public int size() {
155.1043 +            return size;
155.1044 +        }
155.1045 +        public boolean contains(Object o) {
155.1046 +            return containsValue(o);
155.1047 +        }
155.1048 +        public boolean remove(Object o) {
155.1049 +            for (Iterator<V> i = iterator(); i.hasNext(); ) {
155.1050 +                if (i.next() == o) {
155.1051 +                    i.remove();
155.1052 +                    return true;
155.1053 +                }
155.1054 +            }
155.1055 +            return false;
155.1056 +        }
155.1057 +        public void clear() {
155.1058 +            IdentityHashMap.this.clear();
155.1059 +        }
155.1060 +    }
155.1061 +
155.1062 +    /**
155.1063 +     * Returns a {@link Set} view of the mappings contained in this map.
155.1064 +     * Each element in the returned set is a reference-equality-based
155.1065 +     * <tt>Map.Entry</tt>.  The set is backed by the map, so changes
155.1066 +     * to the map are reflected in the set, and vice-versa.  If the
155.1067 +     * map is modified while an iteration over the set is in progress,
155.1068 +     * the results of the iteration are undefined.  The set supports
155.1069 +     * element removal, which removes the corresponding mapping from
155.1070 +     * the map, via the <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
155.1071 +     * <tt>removeAll</tt>, <tt>retainAll</tt> and <tt>clear</tt>
155.1072 +     * methods.  It does not support the <tt>add</tt> or
155.1073 +     * <tt>addAll</tt> methods.
155.1074 +     *
155.1075 +     * <p>Like the backing map, the <tt>Map.Entry</tt> objects in the set
155.1076 +     * returned by this method define key and value equality as
155.1077 +     * reference-equality rather than object-equality.  This affects the
155.1078 +     * behavior of the <tt>equals</tt> and <tt>hashCode</tt> methods of these
155.1079 +     * <tt>Map.Entry</tt> objects.  A reference-equality based <tt>Map.Entry
155.1080 +     * e</tt> is equal to an object <tt>o</tt> if and only if <tt>o</tt> is a
155.1081 +     * <tt>Map.Entry</tt> and <tt>e.getKey()==o.getKey() &amp;&amp;
155.1082 +     * e.getValue()==o.getValue()</tt>.  To accommodate these equals
155.1083 +     * semantics, the <tt>hashCode</tt> method returns
155.1084 +     * <tt>System.identityHashCode(e.getKey()) ^
155.1085 +     * System.identityHashCode(e.getValue())</tt>.
155.1086 +     *
155.1087 +     * <p><b>Owing to the reference-equality-based semantics of the
155.1088 +     * <tt>Map.Entry</tt> instances in the set returned by this method,
155.1089 +     * it is possible that the symmetry and transitivity requirements of
155.1090 +     * the {@link Object#equals(Object)} contract may be violated if any of
155.1091 +     * the entries in the set is compared to a normal map entry, or if
155.1092 +     * the set returned by this method is compared to a set of normal map
155.1093 +     * entries (such as would be returned by a call to this method on a normal
155.1094 +     * map).  However, the <tt>Object.equals</tt> contract is guaranteed to
155.1095 +     * hold among identity-based map entries, and among sets of such entries.
155.1096 +     * </b>
155.1097 +     *
155.1098 +     * @return a set view of the identity-mappings contained in this map
155.1099 +     */
155.1100 +    public Set<Map.Entry<K,V>> entrySet() {
155.1101 +        Set<Map.Entry<K,V>> es = entrySet;
155.1102 +        if (es != null)
155.1103 +            return es;
155.1104 +        else
155.1105 +            return entrySet = new EntrySet();
155.1106 +    }
155.1107 +
155.1108 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
155.1109 +        public Iterator<Map.Entry<K,V>> iterator() {
155.1110 +            return new EntryIterator();
155.1111 +        }
155.1112 +        public boolean contains(Object o) {
155.1113 +            if (!(o instanceof Map.Entry))
155.1114 +                return false;
155.1115 +            Map.Entry entry = (Map.Entry)o;
155.1116 +            return containsMapping(entry.getKey(), entry.getValue());
155.1117 +        }
155.1118 +        public boolean remove(Object o) {
155.1119 +            if (!(o instanceof Map.Entry))
155.1120 +                return false;
155.1121 +            Map.Entry entry = (Map.Entry)o;
155.1122 +            return removeMapping(entry.getKey(), entry.getValue());
155.1123 +        }
155.1124 +        public int size() {
155.1125 +            return size;
155.1126 +        }
155.1127 +        public void clear() {
155.1128 +            IdentityHashMap.this.clear();
155.1129 +        }
155.1130 +        /*
155.1131 +         * Must revert from AbstractSet's impl to AbstractCollection's, as
155.1132 +         * the former contains an optimization that results in incorrect
155.1133 +         * behavior when c is a smaller "normal" (non-identity-based) Set.
155.1134 +         */
155.1135 +        public boolean removeAll(Collection<?> c) {
155.1136 +            boolean modified = false;
155.1137 +            for (Iterator<Map.Entry<K,V>> i = iterator(); i.hasNext(); ) {
155.1138 +                if (c.contains(i.next())) {
155.1139 +                    i.remove();
155.1140 +                    modified = true;
155.1141 +                }
155.1142 +            }
155.1143 +            return modified;
155.1144 +        }
155.1145 +
155.1146 +        public Object[] toArray() {
155.1147 +            int size = size();
155.1148 +            Object[] result = new Object[size];
155.1149 +            Iterator<Map.Entry<K,V>> it = iterator();
155.1150 +            for (int i = 0; i < size; i++)
155.1151 +                result[i] = new AbstractMap.SimpleEntry<>(it.next());
155.1152 +            return result;
155.1153 +        }
155.1154 +
155.1155 +        @SuppressWarnings("unchecked")
155.1156 +        public <T> T[] toArray(T[] a) {
155.1157 +            int size = size();
155.1158 +            if (a.length < size)
155.1159 +                a = (T[])java.lang.reflect.Array
155.1160 +                    .newInstance(a.getClass().getComponentType(), size);
155.1161 +            Iterator<Map.Entry<K,V>> it = iterator();
155.1162 +            for (int i = 0; i < size; i++)
155.1163 +                a[i] = (T) new AbstractMap.SimpleEntry<>(it.next());
155.1164 +            if (a.length > size)
155.1165 +                a[size] = null;
155.1166 +            return a;
155.1167 +        }
155.1168 +    }
155.1169 +
155.1170 +
155.1171 +    private static final long serialVersionUID = 8188218128353913216L;
155.1172 +
155.1173 +    /**
155.1174 +     * Save the state of the <tt>IdentityHashMap</tt> instance to a stream
155.1175 +     * (i.e., serialize it).
155.1176 +     *
155.1177 +     * @serialData The <i>size</i> of the HashMap (the number of key-value
155.1178 +     *          mappings) (<tt>int</tt>), followed by the key (Object) and
155.1179 +     *          value (Object) for each key-value mapping represented by the
155.1180 +     *          IdentityHashMap.  The key-value mappings are emitted in no
155.1181 +     *          particular order.
155.1182 +     */
155.1183 +    private void writeObject(java.io.ObjectOutputStream s)
155.1184 +        throws java.io.IOException  {
155.1185 +        // Write out and any hidden stuff
155.1186 +        s.defaultWriteObject();
155.1187 +
155.1188 +        // Write out size (number of Mappings)
155.1189 +        s.writeInt(size);
155.1190 +
155.1191 +        // Write out keys and values (alternating)
155.1192 +        Object[] tab = table;
155.1193 +        for (int i = 0; i < tab.length; i += 2) {
155.1194 +            Object key = tab[i];
155.1195 +            if (key != null) {
155.1196 +                s.writeObject(unmaskNull(key));
155.1197 +                s.writeObject(tab[i + 1]);
155.1198 +            }
155.1199 +        }
155.1200 +    }
155.1201 +
155.1202 +    /**
155.1203 +     * Reconstitute the <tt>IdentityHashMap</tt> instance from a stream (i.e.,
155.1204 +     * deserialize it).
155.1205 +     */
155.1206 +    private void readObject(java.io.ObjectInputStream s)
155.1207 +        throws java.io.IOException, ClassNotFoundException  {
155.1208 +        // Read in any hidden stuff
155.1209 +        s.defaultReadObject();
155.1210 +
155.1211 +        // Read in size (number of Mappings)
155.1212 +        int size = s.readInt();
155.1213 +
155.1214 +        // Allow for 33% growth (i.e., capacity is >= 2* size()).
155.1215 +        init(capacity((size*4)/3));
155.1216 +
155.1217 +        // Read the keys and values, and put the mappings in the table
155.1218 +        for (int i=0; i<size; i++) {
155.1219 +            K key = (K) s.readObject();
155.1220 +            V value = (V) s.readObject();
155.1221 +            putForCreate(key, value);
155.1222 +        }
155.1223 +    }
155.1224 +
155.1225 +    /**
155.1226 +     * The put method for readObject.  It does not resize the table,
155.1227 +     * update modCount, etc.
155.1228 +     */
155.1229 +    private void putForCreate(K key, V value)
155.1230 +        throws IOException
155.1231 +    {
155.1232 +        K k = (K)maskNull(key);
155.1233 +        Object[] tab = table;
155.1234 +        int len = tab.length;
155.1235 +        int i = hash(k, len);
155.1236 +
155.1237 +        Object item;
155.1238 +        while ( (item = tab[i]) != null) {
155.1239 +            if (item == k)
155.1240 +                throw new java.io.StreamCorruptedException();
155.1241 +            i = nextKeyIndex(i, len);
155.1242 +        }
155.1243 +        tab[i] = k;
155.1244 +        tab[i + 1] = value;
155.1245 +    }
155.1246 +}
   156.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   156.2 +++ b/rt/emul/compact/src/main/java/java/util/JumboEnumSet.java	Mon Oct 07 14:20:58 2013 +0200
   156.3 @@ -0,0 +1,375 @@
   156.4 +/*
   156.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   156.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   156.7 + *
   156.8 + * This code is free software; you can redistribute it and/or modify it
   156.9 + * under the terms of the GNU General Public License version 2 only, as
  156.10 + * published by the Free Software Foundation.  Oracle designates this
  156.11 + * particular file as subject to the "Classpath" exception as provided
  156.12 + * by Oracle in the LICENSE file that accompanied this code.
  156.13 + *
  156.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  156.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  156.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  156.17 + * version 2 for more details (a copy is included in the LICENSE file that
  156.18 + * accompanied this code).
  156.19 + *
  156.20 + * You should have received a copy of the GNU General Public License version
  156.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  156.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  156.23 + *
  156.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  156.25 + * or visit www.oracle.com if you need additional information or have any
  156.26 + * questions.
  156.27 + */
  156.28 +
  156.29 +package java.util;
  156.30 +
  156.31 +/**
  156.32 + * Private implementation class for EnumSet, for "jumbo" enum types
  156.33 + * (i.e., those with more than 64 elements).
  156.34 + *
  156.35 + * @author Josh Bloch
  156.36 + * @since 1.5
  156.37 + * @serial exclude
  156.38 + */
  156.39 +class JumboEnumSet<E extends Enum<E>> extends EnumSet<E> {
  156.40 +    private static final long serialVersionUID = 334349849919042784L;
  156.41 +
  156.42 +    /**
  156.43 +     * Bit vector representation of this set.  The ith bit of the jth
  156.44 +     * element of this array represents the  presence of universe[64*j +i]
  156.45 +     * in this set.
  156.46 +     */
  156.47 +    private long elements[];
  156.48 +
  156.49 +    // Redundant - maintained for performance
  156.50 +    private int size = 0;
  156.51 +
  156.52 +    JumboEnumSet(Class<E>elementType, Enum[] universe) {
  156.53 +        super(elementType, universe);
  156.54 +        elements = new long[(universe.length + 63) >>> 6];
  156.55 +    }
  156.56 +
  156.57 +    void addRange(E from, E to) {
  156.58 +        int fromIndex = from.ordinal() >>> 6;
  156.59 +        int toIndex = to.ordinal() >>> 6;
  156.60 +
  156.61 +        if (fromIndex == toIndex) {
  156.62 +            elements[fromIndex] = (-1L >>>  (from.ordinal() - to.ordinal() - 1))
  156.63 +                            << from.ordinal();
  156.64 +        } else {
  156.65 +            elements[fromIndex] = (-1L << from.ordinal());
  156.66 +            for (int i = fromIndex + 1; i < toIndex; i++)
  156.67 +                elements[i] = -1;
  156.68 +            elements[toIndex] = -1L >>> (63 - to.ordinal());
  156.69 +        }
  156.70 +        size = to.ordinal() - from.ordinal() + 1;
  156.71 +    }
  156.72 +
  156.73 +    void addAll() {
  156.74 +        for (int i = 0; i < elements.length; i++)
  156.75 +            elements[i] = -1;
  156.76 +        elements[elements.length - 1] >>>= -universe.length;
  156.77 +        size = universe.length;
  156.78 +    }
  156.79 +
  156.80 +    void complement() {
  156.81 +        for (int i = 0; i < elements.length; i++)
  156.82 +            elements[i] = ~elements[i];
  156.83 +        elements[elements.length - 1] &= (-1L >>> -universe.length);
  156.84 +        size = universe.length - size;
  156.85 +    }
  156.86 +
  156.87 +    /**
  156.88 +     * Returns an iterator over the elements contained in this set.  The
  156.89 +     * iterator traverses the elements in their <i>natural order</i> (which is
  156.90 +     * the order in which the enum constants are declared). The returned
  156.91 +     * Iterator is a "weakly consistent" iterator that will never throw {@link
  156.92 +     * ConcurrentModificationException}.
  156.93 +     *
  156.94 +     * @return an iterator over the elements contained in this set
  156.95 +     */
  156.96 +    public Iterator<E> iterator() {
  156.97 +        return new EnumSetIterator<>();
  156.98 +    }
  156.99 +
 156.100 +    private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
 156.101 +        /**
 156.102 +         * A bit vector representing the elements in the current "word"
 156.103 +         * of the set not yet returned by this iterator.
 156.104 +         */
 156.105 +        long unseen;
 156.106 +
 156.107 +        /**
 156.108 +         * The index corresponding to unseen in the elements array.
 156.109 +         */
 156.110 +        int unseenIndex = 0;
 156.111 +
 156.112 +        /**
 156.113 +         * The bit representing the last element returned by this iterator
 156.114 +         * but not removed, or zero if no such element exists.
 156.115 +         */
 156.116 +        long lastReturned = 0;
 156.117 +
 156.118 +        /**
 156.119 +         * The index corresponding to lastReturned in the elements array.
 156.120 +         */
 156.121 +        int lastReturnedIndex = 0;
 156.122 +
 156.123 +        EnumSetIterator() {
 156.124 +            unseen = elements[0];
 156.125 +        }
 156.126 +
 156.127 +        public boolean hasNext() {
 156.128 +            while (unseen == 0 && unseenIndex < elements.length - 1)
 156.129 +                unseen = elements[++unseenIndex];
 156.130 +            return unseen != 0;
 156.131 +        }
 156.132 +
 156.133 +        public E next() {
 156.134 +            if (!hasNext())
 156.135 +                throw new NoSuchElementException();
 156.136 +            lastReturned = unseen & -unseen;
 156.137 +            lastReturnedIndex = unseenIndex;
 156.138 +            unseen -= lastReturned;
 156.139 +            return (E) universe[(lastReturnedIndex << 6)
 156.140 +                                + Long.numberOfTrailingZeros(lastReturned)];
 156.141 +        }
 156.142 +
 156.143 +        public void remove() {
 156.144 +            if (lastReturned == 0)
 156.145 +                throw new IllegalStateException();
 156.146 +            final long oldElements = elements[lastReturnedIndex];
 156.147 +            elements[lastReturnedIndex] &= ~lastReturned;
 156.148 +            if (oldElements != elements[lastReturnedIndex]) {
 156.149 +                size--;
 156.150 +            }
 156.151 +            lastReturned = 0;
 156.152 +        }
 156.153 +    }
 156.154 +
 156.155 +    /**
 156.156 +     * Returns the number of elements in this set.
 156.157 +     *
 156.158 +     * @return the number of elements in this set
 156.159 +     */
 156.160 +    public int size() {
 156.161 +        return size;
 156.162 +    }
 156.163 +
 156.164 +    /**
 156.165 +     * Returns <tt>true</tt> if this set contains no elements.
 156.166 +     *
 156.167 +     * @return <tt>true</tt> if this set contains no elements
 156.168 +     */
 156.169 +    public boolean isEmpty() {
 156.170 +        return size == 0;
 156.171 +    }
 156.172 +
 156.173 +    /**
 156.174 +     * Returns <tt>true</tt> if this set contains the specified element.
 156.175 +     *
 156.176 +     * @param e element to be checked for containment in this collection
 156.177 +     * @return <tt>true</tt> if this set contains the specified element
 156.178 +     */
 156.179 +    public boolean contains(Object e) {
 156.180 +        if (e == null)
 156.181 +            return false;
 156.182 +        Class eClass = e.getClass();
 156.183 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 156.184 +            return false;
 156.185 +
 156.186 +        int eOrdinal = ((Enum)e).ordinal();
 156.187 +        return (elements[eOrdinal >>> 6] & (1L << eOrdinal)) != 0;
 156.188 +    }
 156.189 +
 156.190 +    // Modification Operations
 156.191 +
 156.192 +    /**
 156.193 +     * Adds the specified element to this set if it is not already present.
 156.194 +     *
 156.195 +     * @param e element to be added to this set
 156.196 +     * @return <tt>true</tt> if the set changed as a result of the call
 156.197 +     *
 156.198 +     * @throws NullPointerException if <tt>e</tt> is null
 156.199 +     */
 156.200 +    public boolean add(E e) {
 156.201 +        typeCheck(e);
 156.202 +
 156.203 +        int eOrdinal = e.ordinal();
 156.204 +        int eWordNum = eOrdinal >>> 6;
 156.205 +
 156.206 +        long oldElements = elements[eWordNum];
 156.207 +        elements[eWordNum] |= (1L << eOrdinal);
 156.208 +        boolean result = (elements[eWordNum] != oldElements);
 156.209 +        if (result)
 156.210 +            size++;
 156.211 +        return result;
 156.212 +    }
 156.213 +
 156.214 +    /**
 156.215 +     * Removes the specified element from this set if it is present.
 156.216 +     *
 156.217 +     * @param e element to be removed from this set, if present
 156.218 +     * @return <tt>true</tt> if the set contained the specified element
 156.219 +     */
 156.220 +    public boolean remove(Object e) {
 156.221 +        if (e == null)
 156.222 +            return false;
 156.223 +        Class eClass = e.getClass();
 156.224 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 156.225 +            return false;
 156.226 +        int eOrdinal = ((Enum)e).ordinal();
 156.227 +        int eWordNum = eOrdinal >>> 6;
 156.228 +
 156.229 +        long oldElements = elements[eWordNum];
 156.230 +        elements[eWordNum] &= ~(1L << eOrdinal);
 156.231 +        boolean result = (elements[eWordNum] != oldElements);
 156.232 +        if (result)
 156.233 +            size--;
 156.234 +        return result;
 156.235 +    }
 156.236 +
 156.237 +    // Bulk Operations
 156.238 +
 156.239 +    /**
 156.240 +     * Returns <tt>true</tt> if this set contains all of the elements
 156.241 +     * in the specified collection.
 156.242 +     *
 156.243 +     * @param c collection to be checked for containment in this set
 156.244 +     * @return <tt>true</tt> if this set contains all of the elements
 156.245 +     *        in the specified collection
 156.246 +     * @throws NullPointerException if the specified collection is null
 156.247 +     */
 156.248 +    public boolean containsAll(Collection<?> c) {
 156.249 +        if (!(c instanceof JumboEnumSet))
 156.250 +            return super.containsAll(c);
 156.251 +
 156.252 +        JumboEnumSet es = (JumboEnumSet)c;
 156.253 +        if (es.elementType != elementType)
 156.254 +            return es.isEmpty();
 156.255 +
 156.256 +        for (int i = 0; i < elements.length; i++)
 156.257 +            if ((es.elements[i] & ~elements[i]) != 0)
 156.258 +                return false;
 156.259 +        return true;
 156.260 +    }
 156.261 +
 156.262 +    /**
 156.263 +     * Adds all of the elements in the specified collection to this set.
 156.264 +     *
 156.265 +     * @param c collection whose elements are to be added to this set
 156.266 +     * @return <tt>true</tt> if this set changed as a result of the call
 156.267 +     * @throws NullPointerException if the specified collection or any of
 156.268 +     *     its elements are null
 156.269 +     */
 156.270 +    public boolean addAll(Collection<? extends E> c) {
 156.271 +        if (!(c instanceof JumboEnumSet))
 156.272 +            return super.addAll(c);
 156.273 +
 156.274 +        JumboEnumSet es = (JumboEnumSet)c;
 156.275 +        if (es.elementType != elementType) {
 156.276 +            if (es.isEmpty())
 156.277 +                return false;
 156.278 +            else
 156.279 +                throw new ClassCastException(
 156.280 +                    es.elementType + " != " + elementType);
 156.281 +        }
 156.282 +
 156.283 +        for (int i = 0; i < elements.length; i++)
 156.284 +            elements[i] |= es.elements[i];
 156.285 +        return recalculateSize();
 156.286 +    }
 156.287 +
 156.288 +    /**
 156.289 +     * Removes from this set all of its elements that are contained in
 156.290 +     * the specified collection.
 156.291 +     *
 156.292 +     * @param c elements to be removed from this set
 156.293 +     * @return <tt>true</tt> if this set changed as a result of the call
 156.294 +     * @throws NullPointerException if the specified collection is null
 156.295 +     */
 156.296 +    public boolean removeAll(Collection<?> c) {
 156.297 +        if (!(c instanceof JumboEnumSet))
 156.298 +            return super.removeAll(c);
 156.299 +
 156.300 +        JumboEnumSet es = (JumboEnumSet)c;
 156.301 +        if (es.elementType != elementType)
 156.302 +            return false;
 156.303 +
 156.304 +        for (int i = 0; i < elements.length; i++)
 156.305 +            elements[i] &= ~es.elements[i];
 156.306 +        return recalculateSize();
 156.307 +    }
 156.308 +
 156.309 +    /**
 156.310 +     * Retains only the elements in this set that are contained in the
 156.311 +     * specified collection.
 156.312 +     *
 156.313 +     * @param c elements to be retained in this set
 156.314 +     * @return <tt>true</tt> if this set changed as a result of the call
 156.315 +     * @throws NullPointerException if the specified collection is null
 156.316 +     */
 156.317 +    public boolean retainAll(Collection<?> c) {
 156.318 +        if (!(c instanceof JumboEnumSet))
 156.319 +            return super.retainAll(c);
 156.320 +
 156.321 +        JumboEnumSet<?> es = (JumboEnumSet<?>)c;
 156.322 +        if (es.elementType != elementType) {
 156.323 +            boolean changed = (size != 0);
 156.324 +            clear();
 156.325 +            return changed;
 156.326 +        }
 156.327 +
 156.328 +        for (int i = 0; i < elements.length; i++)
 156.329 +            elements[i] &= es.elements[i];
 156.330 +        return recalculateSize();
 156.331 +    }
 156.332 +
 156.333 +    /**
 156.334 +     * Removes all of the elements from this set.
 156.335 +     */
 156.336 +    public void clear() {
 156.337 +        Arrays.fill(elements, 0);
 156.338 +        size = 0;
 156.339 +    }
 156.340 +
 156.341 +    /**
 156.342 +     * Compares the specified object with this set for equality.  Returns
 156.343 +     * <tt>true</tt> if the given object is also a set, the two sets have
 156.344 +     * the same size, and every member of the given set is contained in
 156.345 +     * this set.
 156.346 +     *
 156.347 +     * @param e object to be compared for equality with this set
 156.348 +     * @return <tt>true</tt> if the specified object is equal to this set
 156.349 +     */
 156.350 +    public boolean equals(Object o) {
 156.351 +        if (!(o instanceof JumboEnumSet))
 156.352 +            return super.equals(o);
 156.353 +
 156.354 +        JumboEnumSet es = (JumboEnumSet)o;
 156.355 +        if (es.elementType != elementType)
 156.356 +            return size == 0 && es.size == 0;
 156.357 +
 156.358 +        return Arrays.equals(es.elements, elements);
 156.359 +    }
 156.360 +
 156.361 +    /**
 156.362 +     * Recalculates the size of the set.  Returns true if it's changed.
 156.363 +     */
 156.364 +    private boolean recalculateSize() {
 156.365 +        int oldSize = size;
 156.366 +        size = 0;
 156.367 +        for (long elt : elements)
 156.368 +            size += Long.bitCount(elt);
 156.369 +
 156.370 +        return size != oldSize;
 156.371 +    }
 156.372 +
 156.373 +    public EnumSet<E> clone() {
 156.374 +        JumboEnumSet<E> result = (JumboEnumSet<E>) super.clone();
 156.375 +        result.elements = result.elements.clone();
 156.376 +        return result;
 156.377 +    }
 156.378 +}
   157.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   157.2 +++ b/rt/emul/compact/src/main/java/java/util/LinkedHashSet.java	Mon Oct 07 14:20:58 2013 +0200
   157.3 @@ -0,0 +1,171 @@
   157.4 +/*
   157.5 + * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
   157.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   157.7 + *
   157.8 + * This code is free software; you can redistribute it and/or modify it
   157.9 + * under the terms of the GNU General Public License version 2 only, as
  157.10 + * published by the Free Software Foundation.  Oracle designates this
  157.11 + * particular file as subject to the "Classpath" exception as provided
  157.12 + * by Oracle in the LICENSE file that accompanied this code.
  157.13 + *
  157.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  157.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  157.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  157.17 + * version 2 for more details (a copy is included in the LICENSE file that
  157.18 + * accompanied this code).
  157.19 + *
  157.20 + * You should have received a copy of the GNU General Public License version
  157.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  157.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  157.23 + *
  157.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  157.25 + * or visit www.oracle.com if you need additional information or have any
  157.26 + * questions.
  157.27 + */
  157.28 +
  157.29 +package java.util;
  157.30 +
  157.31 +/**
  157.32 + * <p>Hash table and linked list implementation of the <tt>Set</tt> interface,
  157.33 + * with predictable iteration order.  This implementation differs from
  157.34 + * <tt>HashSet</tt> in that it maintains a doubly-linked list running through
  157.35 + * all of its entries.  This linked list defines the iteration ordering,
  157.36 + * which is the order in which elements were inserted into the set
  157.37 + * (<i>insertion-order</i>).  Note that insertion order is <i>not</i> affected
  157.38 + * if an element is <i>re-inserted</i> into the set.  (An element <tt>e</tt>
  157.39 + * is reinserted into a set <tt>s</tt> if <tt>s.add(e)</tt> is invoked when
  157.40 + * <tt>s.contains(e)</tt> would return <tt>true</tt> immediately prior to
  157.41 + * the invocation.)
  157.42 + *
  157.43 + * <p>This implementation spares its clients from the unspecified, generally
  157.44 + * chaotic ordering provided by {@link HashSet}, without incurring the
  157.45 + * increased cost associated with {@link TreeSet}.  It can be used to
  157.46 + * produce a copy of a set that has the same order as the original, regardless
  157.47 + * of the original set's implementation:
  157.48 + * <pre>
  157.49 + *     void foo(Set s) {
  157.50 + *         Set copy = new LinkedHashSet(s);
  157.51 + *         ...
  157.52 + *     }
  157.53 + * </pre>
  157.54 + * This technique is particularly useful if a module takes a set on input,
  157.55 + * copies it, and later returns results whose order is determined by that of
  157.56 + * the copy.  (Clients generally appreciate having things returned in the same
  157.57 + * order they were presented.)
  157.58 + *
  157.59 + * <p>This class provides all of the optional <tt>Set</tt> operations, and
  157.60 + * permits null elements.  Like <tt>HashSet</tt>, it provides constant-time
  157.61 + * performance for the basic operations (<tt>add</tt>, <tt>contains</tt> and
  157.62 + * <tt>remove</tt>), assuming the hash function disperses elements
  157.63 + * properly among the buckets.  Performance is likely to be just slightly
  157.64 + * below that of <tt>HashSet</tt>, due to the added expense of maintaining the
  157.65 + * linked list, with one exception: Iteration over a <tt>LinkedHashSet</tt>
  157.66 + * requires time proportional to the <i>size</i> of the set, regardless of
  157.67 + * its capacity.  Iteration over a <tt>HashSet</tt> is likely to be more
  157.68 + * expensive, requiring time proportional to its <i>capacity</i>.
  157.69 + *
  157.70 + * <p>A linked hash set has two parameters that affect its performance:
  157.71 + * <i>initial capacity</i> and <i>load factor</i>.  They are defined precisely
  157.72 + * as for <tt>HashSet</tt>.  Note, however, that the penalty for choosing an
  157.73 + * excessively high value for initial capacity is less severe for this class
  157.74 + * than for <tt>HashSet</tt>, as iteration times for this class are unaffected
  157.75 + * by capacity.
  157.76 + *
  157.77 + * <p><strong>Note that this implementation is not synchronized.</strong>
  157.78 + * If multiple threads access a linked hash set concurrently, and at least
  157.79 + * one of the threads modifies the set, it <em>must</em> be synchronized
  157.80 + * externally.  This is typically accomplished by synchronizing on some
  157.81 + * object that naturally encapsulates the set.
  157.82 + *
  157.83 + * If no such object exists, the set should be "wrapped" using the
  157.84 + * {@link Collections#synchronizedSet Collections.synchronizedSet}
  157.85 + * method.  This is best done at creation time, to prevent accidental
  157.86 + * unsynchronized access to the set: <pre>
  157.87 + *   Set s = Collections.synchronizedSet(new LinkedHashSet(...));</pre>
  157.88 + *
  157.89 + * <p>The iterators returned by this class's <tt>iterator</tt> method are
  157.90 + * <em>fail-fast</em>: if the set is modified at any time after the iterator
  157.91 + * is created, in any way except through the iterator's own <tt>remove</tt>
  157.92 + * method, the iterator will throw a {@link ConcurrentModificationException}.
  157.93 + * Thus, in the face of concurrent modification, the iterator fails quickly
  157.94 + * and cleanly, rather than risking arbitrary, non-deterministic behavior at
  157.95 + * an undetermined time in the future.
  157.96 + *
  157.97 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  157.98 + * as it is, generally speaking, impossible to make any hard guarantees in the
  157.99 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 157.100 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 157.101 + * Therefore, it would be wrong to write a program that depended on this
 157.102 + * exception for its correctness:   <i>the fail-fast behavior of iterators
 157.103 + * should be used only to detect bugs.</i>
 157.104 + *
 157.105 + * <p>This class is a member of the
 157.106 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 157.107 + * Java Collections Framework</a>.
 157.108 + *
 157.109 + * @param <E> the type of elements maintained by this set
 157.110 + *
 157.111 + * @author  Josh Bloch
 157.112 + * @see     Object#hashCode()
 157.113 + * @see     Collection
 157.114 + * @see     Set
 157.115 + * @see     HashSet
 157.116 + * @see     TreeSet
 157.117 + * @see     Hashtable
 157.118 + * @since   1.4
 157.119 + */
 157.120 +
 157.121 +public class LinkedHashSet<E>
 157.122 +    extends HashSet<E>
 157.123 +    implements Set<E>, Cloneable, java.io.Serializable {
 157.124 +
 157.125 +    private static final long serialVersionUID = -2851667679971038690L;
 157.126 +
 157.127 +    /**
 157.128 +     * Constructs a new, empty linked hash set with the specified initial
 157.129 +     * capacity and load factor.
 157.130 +     *
 157.131 +     * @param      initialCapacity the initial capacity of the linked hash set
 157.132 +     * @param      loadFactor      the load factor of the linked hash set
 157.133 +     * @throws     IllegalArgumentException  if the initial capacity is less
 157.134 +     *               than zero, or if the load factor is nonpositive
 157.135 +     */
 157.136 +    public LinkedHashSet(int initialCapacity, float loadFactor) {
 157.137 +        super(initialCapacity, loadFactor, true);
 157.138 +    }
 157.139 +
 157.140 +    /**
 157.141 +     * Constructs a new, empty linked hash set with the specified initial
 157.142 +     * capacity and the default load factor (0.75).
 157.143 +     *
 157.144 +     * @param   initialCapacity   the initial capacity of the LinkedHashSet
 157.145 +     * @throws  IllegalArgumentException if the initial capacity is less
 157.146 +     *              than zero
 157.147 +     */
 157.148 +    public LinkedHashSet(int initialCapacity) {
 157.149 +        super(initialCapacity, .75f, true);
 157.150 +    }
 157.151 +
 157.152 +    /**
 157.153 +     * Constructs a new, empty linked hash set with the default initial
 157.154 +     * capacity (16) and load factor (0.75).
 157.155 +     */
 157.156 +    public LinkedHashSet() {
 157.157 +        super(16, .75f, true);
 157.158 +    }
 157.159 +
 157.160 +    /**
 157.161 +     * Constructs a new linked hash set with the same elements as the
 157.162 +     * specified collection.  The linked hash set is created with an initial
 157.163 +     * capacity sufficient to hold the elements in the specified collection
 157.164 +     * and the default load factor (0.75).
 157.165 +     *
 157.166 +     * @param c  the collection whose elements are to be placed into
 157.167 +     *           this set
 157.168 +     * @throws NullPointerException if the specified collection is null
 157.169 +     */
 157.170 +    public LinkedHashSet(Collection<? extends E> c) {
 157.171 +        super(Math.max(2*c.size(), 11), .75f, true);
 157.172 +        addAll(c);
 157.173 +    }
 157.174 +}
   158.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   158.2 +++ b/rt/emul/compact/src/main/java/java/util/NavigableMap.java	Mon Oct 07 14:20:58 2013 +0200
   158.3 @@ -0,0 +1,424 @@
   158.4 +/*
   158.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   158.6 + *
   158.7 + * This code is free software; you can redistribute it and/or modify it
   158.8 + * under the terms of the GNU General Public License version 2 only, as
   158.9 + * published by the Free Software Foundation.  Oracle designates this
  158.10 + * particular file as subject to the "Classpath" exception as provided
  158.11 + * by Oracle in the LICENSE file that accompanied this code.
  158.12 + *
  158.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  158.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  158.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  158.16 + * version 2 for more details (a copy is included in the LICENSE file that
  158.17 + * accompanied this code).
  158.18 + *
  158.19 + * You should have received a copy of the GNU General Public License version
  158.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  158.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  158.22 + *
  158.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  158.24 + * or visit www.oracle.com if you need additional information or have any
  158.25 + * questions.
  158.26 + */
  158.27 +
  158.28 +/*
  158.29 + * This file is available under and governed by the GNU General Public
  158.30 + * License version 2 only, as published by the Free Software Foundation.
  158.31 + * However, the following notice accompanied the original version of this
  158.32 + * file:
  158.33 + *
  158.34 + * Written by Doug Lea and Josh Bloch with assistance from members of JCP
  158.35 + * JSR-166 Expert Group and released to the public domain, as explained at
  158.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  158.37 + */
  158.38 +
  158.39 +package java.util;
  158.40 +
  158.41 +/**
  158.42 + * A {@link SortedMap} extended with navigation methods returning the
  158.43 + * closest matches for given search targets. Methods
  158.44 + * {@code lowerEntry}, {@code floorEntry}, {@code ceilingEntry},
  158.45 + * and {@code higherEntry} return {@code Map.Entry} objects
  158.46 + * associated with keys respectively less than, less than or equal,
  158.47 + * greater than or equal, and greater than a given key, returning
  158.48 + * {@code null} if there is no such key.  Similarly, methods
  158.49 + * {@code lowerKey}, {@code floorKey}, {@code ceilingKey}, and
  158.50 + * {@code higherKey} return only the associated keys. All of these
  158.51 + * methods are designed for locating, not traversing entries.
  158.52 + *
  158.53 + * <p>A {@code NavigableMap} may be accessed and traversed in either
  158.54 + * ascending or descending key order.  The {@code descendingMap}
  158.55 + * method returns a view of the map with the senses of all relational
  158.56 + * and directional methods inverted. The performance of ascending
  158.57 + * operations and views is likely to be faster than that of descending
  158.58 + * ones.  Methods {@code subMap}, {@code headMap},
  158.59 + * and {@code tailMap} differ from the like-named {@code
  158.60 + * SortedMap} methods in accepting additional arguments describing
  158.61 + * whether lower and upper bounds are inclusive versus exclusive.
  158.62 + * Submaps of any {@code NavigableMap} must implement the {@code
  158.63 + * NavigableMap} interface.
  158.64 + *
  158.65 + * <p>This interface additionally defines methods {@code firstEntry},
  158.66 + * {@code pollFirstEntry}, {@code lastEntry}, and
  158.67 + * {@code pollLastEntry} that return and/or remove the least and
  158.68 + * greatest mappings, if any exist, else returning {@code null}.
  158.69 + *
  158.70 + * <p>Implementations of entry-returning methods are expected to
  158.71 + * return {@code Map.Entry} pairs representing snapshots of mappings
  158.72 + * at the time they were produced, and thus generally do <em>not</em>
  158.73 + * support the optional {@code Entry.setValue} method. Note however
  158.74 + * that it is possible to change mappings in the associated map using
  158.75 + * method {@code put}.
  158.76 + *
  158.77 + * <p>Methods
  158.78 + * {@link #subMap(Object, Object) subMap(K, K)},
  158.79 + * {@link #headMap(Object) headMap(K)}, and
  158.80 + * {@link #tailMap(Object) tailMap(K)}
  158.81 + * are specified to return {@code SortedMap} to allow existing
  158.82 + * implementations of {@code SortedMap} to be compatibly retrofitted to
  158.83 + * implement {@code NavigableMap}, but extensions and implementations
  158.84 + * of this interface are encouraged to override these methods to return
  158.85 + * {@code NavigableMap}.  Similarly,
  158.86 + * {@link #keySet()} can be overriden to return {@code NavigableSet}.
  158.87 + *
  158.88 + * <p>This interface is a member of the
  158.89 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  158.90 + * Java Collections Framework</a>.
  158.91 + *
  158.92 + * @author Doug Lea
  158.93 + * @author Josh Bloch
  158.94 + * @param <K> the type of keys maintained by this map
  158.95 + * @param <V> the type of mapped values
  158.96 + * @since 1.6
  158.97 + */
  158.98 +public interface NavigableMap<K,V> extends SortedMap<K,V> {
  158.99 +    /**
 158.100 +     * Returns a key-value mapping associated with the greatest key
 158.101 +     * strictly less than the given key, or {@code null} if there is
 158.102 +     * no such key.
 158.103 +     *
 158.104 +     * @param key the key
 158.105 +     * @return an entry with the greatest key less than {@code key},
 158.106 +     *         or {@code null} if there is no such key
 158.107 +     * @throws ClassCastException if the specified key cannot be compared
 158.108 +     *         with the keys currently in the map
 158.109 +     * @throws NullPointerException if the specified key is null
 158.110 +     *         and this map does not permit null keys
 158.111 +     */
 158.112 +    Map.Entry<K,V> lowerEntry(K key);
 158.113 +
 158.114 +    /**
 158.115 +     * Returns the greatest key strictly less than the given key, or
 158.116 +     * {@code null} if there is no such key.
 158.117 +     *
 158.118 +     * @param key the key
 158.119 +     * @return the greatest key less than {@code key},
 158.120 +     *         or {@code null} if there is no such key
 158.121 +     * @throws ClassCastException if the specified key cannot be compared
 158.122 +     *         with the keys currently in the map
 158.123 +     * @throws NullPointerException if the specified key is null
 158.124 +     *         and this map does not permit null keys
 158.125 +     */
 158.126 +    K lowerKey(K key);
 158.127 +
 158.128 +    /**
 158.129 +     * Returns a key-value mapping associated with the greatest key
 158.130 +     * less than or equal to the given key, or {@code null} if there
 158.131 +     * is no such key.
 158.132 +     *
 158.133 +     * @param key the key
 158.134 +     * @return an entry with the greatest key less than or equal to
 158.135 +     *         {@code key}, or {@code null} if there is no such key
 158.136 +     * @throws ClassCastException if the specified key cannot be compared
 158.137 +     *         with the keys currently in the map
 158.138 +     * @throws NullPointerException if the specified key is null
 158.139 +     *         and this map does not permit null keys
 158.140 +     */
 158.141 +    Map.Entry<K,V> floorEntry(K key);
 158.142 +
 158.143 +    /**
 158.144 +     * Returns the greatest key less than or equal to the given key,
 158.145 +     * or {@code null} if there is no such key.
 158.146 +     *
 158.147 +     * @param key the key
 158.148 +     * @return the greatest key less than or equal to {@code key},
 158.149 +     *         or {@code null} if there is no such key
 158.150 +     * @throws ClassCastException if the specified key cannot be compared
 158.151 +     *         with the keys currently in the map
 158.152 +     * @throws NullPointerException if the specified key is null
 158.153 +     *         and this map does not permit null keys
 158.154 +     */
 158.155 +    K floorKey(K key);
 158.156 +
 158.157 +    /**
 158.158 +     * Returns a key-value mapping associated with the least key
 158.159 +     * greater than or equal to the given key, or {@code null} if
 158.160 +     * there is no such key.
 158.161 +     *
 158.162 +     * @param key the key
 158.163 +     * @return an entry with the least key greater than or equal to
 158.164 +     *         {@code key}, or {@code null} if there is no such key
 158.165 +     * @throws ClassCastException if the specified key cannot be compared
 158.166 +     *         with the keys currently in the map
 158.167 +     * @throws NullPointerException if the specified key is null
 158.168 +     *         and this map does not permit null keys
 158.169 +     */
 158.170 +    Map.Entry<K,V> ceilingEntry(K key);
 158.171 +
 158.172 +    /**
 158.173 +     * Returns the least key greater than or equal to the given key,
 158.174 +     * or {@code null} if there is no such key.
 158.175 +     *
 158.176 +     * @param key the key
 158.177 +     * @return the least key greater than or equal to {@code key},
 158.178 +     *         or {@code null} if there is no such key
 158.179 +     * @throws ClassCastException if the specified key cannot be compared
 158.180 +     *         with the keys currently in the map
 158.181 +     * @throws NullPointerException if the specified key is null
 158.182 +     *         and this map does not permit null keys
 158.183 +     */
 158.184 +    K ceilingKey(K key);
 158.185 +
 158.186 +    /**
 158.187 +     * Returns a key-value mapping associated with the least key
 158.188 +     * strictly greater than the given key, or {@code null} if there
 158.189 +     * is no such key.
 158.190 +     *
 158.191 +     * @param key the key
 158.192 +     * @return an entry with the least key greater than {@code key},
 158.193 +     *         or {@code null} if there is no such key
 158.194 +     * @throws ClassCastException if the specified key cannot be compared
 158.195 +     *         with the keys currently in the map
 158.196 +     * @throws NullPointerException if the specified key is null
 158.197 +     *         and this map does not permit null keys
 158.198 +     */
 158.199 +    Map.Entry<K,V> higherEntry(K key);
 158.200 +
 158.201 +    /**
 158.202 +     * Returns the least key strictly greater than the given key, or
 158.203 +     * {@code null} if there is no such key.
 158.204 +     *
 158.205 +     * @param key the key
 158.206 +     * @return the least key greater than {@code key},
 158.207 +     *         or {@code null} if there is no such key
 158.208 +     * @throws ClassCastException if the specified key cannot be compared
 158.209 +     *         with the keys currently in the map
 158.210 +     * @throws NullPointerException if the specified key is null
 158.211 +     *         and this map does not permit null keys
 158.212 +     */
 158.213 +    K higherKey(K key);
 158.214 +
 158.215 +    /**
 158.216 +     * Returns a key-value mapping associated with the least
 158.217 +     * key in this map, or {@code null} if the map is empty.
 158.218 +     *
 158.219 +     * @return an entry with the least key,
 158.220 +     *         or {@code null} if this map is empty
 158.221 +     */
 158.222 +    Map.Entry<K,V> firstEntry();
 158.223 +
 158.224 +    /**
 158.225 +     * Returns a key-value mapping associated with the greatest
 158.226 +     * key in this map, or {@code null} if the map is empty.
 158.227 +     *
 158.228 +     * @return an entry with the greatest key,
 158.229 +     *         or {@code null} if this map is empty
 158.230 +     */
 158.231 +    Map.Entry<K,V> lastEntry();
 158.232 +
 158.233 +    /**
 158.234 +     * Removes and returns a key-value mapping associated with
 158.235 +     * the least key in this map, or {@code null} if the map is empty.
 158.236 +     *
 158.237 +     * @return the removed first entry of this map,
 158.238 +     *         or {@code null} if this map is empty
 158.239 +     */
 158.240 +    Map.Entry<K,V> pollFirstEntry();
 158.241 +
 158.242 +    /**
 158.243 +     * Removes and returns a key-value mapping associated with
 158.244 +     * the greatest key in this map, or {@code null} if the map is empty.
 158.245 +     *
 158.246 +     * @return the removed last entry of this map,
 158.247 +     *         or {@code null} if this map is empty
 158.248 +     */
 158.249 +    Map.Entry<K,V> pollLastEntry();
 158.250 +
 158.251 +    /**
 158.252 +     * Returns a reverse order view of the mappings contained in this map.
 158.253 +     * The descending map is backed by this map, so changes to the map are
 158.254 +     * reflected in the descending map, and vice-versa.  If either map is
 158.255 +     * modified while an iteration over a collection view of either map
 158.256 +     * is in progress (except through the iterator's own {@code remove}
 158.257 +     * operation), the results of the iteration are undefined.
 158.258 +     *
 158.259 +     * <p>The returned map has an ordering equivalent to
 158.260 +     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
 158.261 +     * The expression {@code m.descendingMap().descendingMap()} returns a
 158.262 +     * view of {@code m} essentially equivalent to {@code m}.
 158.263 +     *
 158.264 +     * @return a reverse order view of this map
 158.265 +     */
 158.266 +    NavigableMap<K,V> descendingMap();
 158.267 +
 158.268 +    /**
 158.269 +     * Returns a {@link NavigableSet} view of the keys contained in this map.
 158.270 +     * The set's iterator returns the keys in ascending order.
 158.271 +     * The set is backed by the map, so changes to the map are reflected in
 158.272 +     * the set, and vice-versa.  If the map is modified while an iteration
 158.273 +     * over the set is in progress (except through the iterator's own {@code
 158.274 +     * remove} operation), the results of the iteration are undefined.  The
 158.275 +     * set supports element removal, which removes the corresponding mapping
 158.276 +     * from the map, via the {@code Iterator.remove}, {@code Set.remove},
 158.277 +     * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
 158.278 +     * It does not support the {@code add} or {@code addAll} operations.
 158.279 +     *
 158.280 +     * @return a navigable set view of the keys in this map
 158.281 +     */
 158.282 +    NavigableSet<K> navigableKeySet();
 158.283 +
 158.284 +    /**
 158.285 +     * Returns a reverse order {@link NavigableSet} view of the keys contained in this map.
 158.286 +     * The set's iterator returns the keys in descending order.
 158.287 +     * The set is backed by the map, so changes to the map are reflected in
 158.288 +     * the set, and vice-versa.  If the map is modified while an iteration
 158.289 +     * over the set is in progress (except through the iterator's own {@code
 158.290 +     * remove} operation), the results of the iteration are undefined.  The
 158.291 +     * set supports element removal, which removes the corresponding mapping
 158.292 +     * from the map, via the {@code Iterator.remove}, {@code Set.remove},
 158.293 +     * {@code removeAll}, {@code retainAll}, and {@code clear} operations.
 158.294 +     * It does not support the {@code add} or {@code addAll} operations.
 158.295 +     *
 158.296 +     * @return a reverse order navigable set view of the keys in this map
 158.297 +     */
 158.298 +    NavigableSet<K> descendingKeySet();
 158.299 +
 158.300 +    /**
 158.301 +     * Returns a view of the portion of this map whose keys range from
 158.302 +     * {@code fromKey} to {@code toKey}.  If {@code fromKey} and
 158.303 +     * {@code toKey} are equal, the returned map is empty unless
 158.304 +     * {@code fromInclusive} and {@code toInclusive} are both true.  The
 158.305 +     * returned map is backed by this map, so changes in the returned map are
 158.306 +     * reflected in this map, and vice-versa.  The returned map supports all
 158.307 +     * optional map operations that this map supports.
 158.308 +     *
 158.309 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 158.310 +     * on an attempt to insert a key outside of its range, or to construct a
 158.311 +     * submap either of whose endpoints lie outside its range.
 158.312 +     *
 158.313 +     * @param fromKey low endpoint of the keys in the returned map
 158.314 +     * @param fromInclusive {@code true} if the low endpoint
 158.315 +     *        is to be included in the returned view
 158.316 +     * @param toKey high endpoint of the keys in the returned map
 158.317 +     * @param toInclusive {@code true} if the high endpoint
 158.318 +     *        is to be included in the returned view
 158.319 +     * @return a view of the portion of this map whose keys range from
 158.320 +     *         {@code fromKey} to {@code toKey}
 158.321 +     * @throws ClassCastException if {@code fromKey} and {@code toKey}
 158.322 +     *         cannot be compared to one another using this map's comparator
 158.323 +     *         (or, if the map has no comparator, using natural ordering).
 158.324 +     *         Implementations may, but are not required to, throw this
 158.325 +     *         exception if {@code fromKey} or {@code toKey}
 158.326 +     *         cannot be compared to keys currently in the map.
 158.327 +     * @throws NullPointerException if {@code fromKey} or {@code toKey}
 158.328 +     *         is null and this map does not permit null keys
 158.329 +     * @throws IllegalArgumentException if {@code fromKey} is greater than
 158.330 +     *         {@code toKey}; or if this map itself has a restricted
 158.331 +     *         range, and {@code fromKey} or {@code toKey} lies
 158.332 +     *         outside the bounds of the range
 158.333 +     */
 158.334 +    NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
 158.335 +                             K toKey,   boolean toInclusive);
 158.336 +
 158.337 +    /**
 158.338 +     * Returns a view of the portion of this map whose keys are less than (or
 158.339 +     * equal to, if {@code inclusive} is true) {@code toKey}.  The returned
 158.340 +     * map is backed by this map, so changes in the returned map are reflected
 158.341 +     * in this map, and vice-versa.  The returned map supports all optional
 158.342 +     * map operations that this map supports.
 158.343 +     *
 158.344 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 158.345 +     * on an attempt to insert a key outside its range.
 158.346 +     *
 158.347 +     * @param toKey high endpoint of the keys in the returned map
 158.348 +     * @param inclusive {@code true} if the high endpoint
 158.349 +     *        is to be included in the returned view
 158.350 +     * @return a view of the portion of this map whose keys are less than
 158.351 +     *         (or equal to, if {@code inclusive} is true) {@code toKey}
 158.352 +     * @throws ClassCastException if {@code toKey} is not compatible
 158.353 +     *         with this map's comparator (or, if the map has no comparator,
 158.354 +     *         if {@code toKey} does not implement {@link Comparable}).
 158.355 +     *         Implementations may, but are not required to, throw this
 158.356 +     *         exception if {@code toKey} cannot be compared to keys
 158.357 +     *         currently in the map.
 158.358 +     * @throws NullPointerException if {@code toKey} is null
 158.359 +     *         and this map does not permit null keys
 158.360 +     * @throws IllegalArgumentException if this map itself has a
 158.361 +     *         restricted range, and {@code toKey} lies outside the
 158.362 +     *         bounds of the range
 158.363 +     */
 158.364 +    NavigableMap<K,V> headMap(K toKey, boolean inclusive);
 158.365 +
 158.366 +    /**
 158.367 +     * Returns a view of the portion of this map whose keys are greater than (or
 158.368 +     * equal to, if {@code inclusive} is true) {@code fromKey}.  The returned
 158.369 +     * map is backed by this map, so changes in the returned map are reflected
 158.370 +     * in this map, and vice-versa.  The returned map supports all optional
 158.371 +     * map operations that this map supports.
 158.372 +     *
 158.373 +     * <p>The returned map will throw an {@code IllegalArgumentException}
 158.374 +     * on an attempt to insert a key outside its range.
 158.375 +     *
 158.376 +     * @param fromKey low endpoint of the keys in the returned map
 158.377 +     * @param inclusive {@code true} if the low endpoint
 158.378 +     *        is to be included in the returned view
 158.379 +     * @return a view of the portion of this map whose keys are greater than
 158.380 +     *         (or equal to, if {@code inclusive} is true) {@code fromKey}
 158.381 +     * @throws ClassCastException if {@code fromKey} is not compatible
 158.382 +     *         with this map's comparator (or, if the map has no comparator,
 158.383 +     *         if {@code fromKey} does not implement {@link Comparable}).
 158.384 +     *         Implementations may, but are not required to, throw this
 158.385 +     *         exception if {@code fromKey} cannot be compared to keys
 158.386 +     *         currently in the map.
 158.387 +     * @throws NullPointerException if {@code fromKey} is null
 158.388 +     *         and this map does not permit null keys
 158.389 +     * @throws IllegalArgumentException if this map itself has a
 158.390 +     *         restricted range, and {@code fromKey} lies outside the
 158.391 +     *         bounds of the range
 158.392 +     */
 158.393 +    NavigableMap<K,V> tailMap(K fromKey, boolean inclusive);
 158.394 +
 158.395 +    /**
 158.396 +     * {@inheritDoc}
 158.397 +     *
 158.398 +     * <p>Equivalent to {@code subMap(fromKey, true, toKey, false)}.
 158.399 +     *
 158.400 +     * @throws ClassCastException       {@inheritDoc}
 158.401 +     * @throws NullPointerException     {@inheritDoc}
 158.402 +     * @throws IllegalArgumentException {@inheritDoc}
 158.403 +     */
 158.404 +    SortedMap<K,V> subMap(K fromKey, K toKey);
 158.405 +
 158.406 +    /**
 158.407 +     * {@inheritDoc}
 158.408 +     *
 158.409 +     * <p>Equivalent to {@code headMap(toKey, false)}.
 158.410 +     *
 158.411 +     * @throws ClassCastException       {@inheritDoc}
 158.412 +     * @throws NullPointerException     {@inheritDoc}
 158.413 +     * @throws IllegalArgumentException {@inheritDoc}
 158.414 +     */
 158.415 +    SortedMap<K,V> headMap(K toKey);
 158.416 +
 158.417 +    /**
 158.418 +     * {@inheritDoc}
 158.419 +     *
 158.420 +     * <p>Equivalent to {@code tailMap(fromKey, true)}.
 158.421 +     *
 158.422 +     * @throws ClassCastException       {@inheritDoc}
 158.423 +     * @throws NullPointerException     {@inheritDoc}
 158.424 +     * @throws IllegalArgumentException {@inheritDoc}
 158.425 +     */
 158.426 +    SortedMap<K,V> tailMap(K fromKey);
 158.427 +}
   159.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   159.2 +++ b/rt/emul/compact/src/main/java/java/util/NavigableSet.java	Mon Oct 07 14:20:58 2013 +0200
   159.3 @@ -0,0 +1,319 @@
   159.4 +/*
   159.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   159.6 + *
   159.7 + * This code is free software; you can redistribute it and/or modify it
   159.8 + * under the terms of the GNU General Public License version 2 only, as
   159.9 + * published by the Free Software Foundation.  Oracle designates this
  159.10 + * particular file as subject to the "Classpath" exception as provided
  159.11 + * by Oracle in the LICENSE file that accompanied this code.
  159.12 + *
  159.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  159.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  159.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  159.16 + * version 2 for more details (a copy is included in the LICENSE file that
  159.17 + * accompanied this code).
  159.18 + *
  159.19 + * You should have received a copy of the GNU General Public License version
  159.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  159.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  159.22 + *
  159.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  159.24 + * or visit www.oracle.com if you need additional information or have any
  159.25 + * questions.
  159.26 + */
  159.27 +
  159.28 +/*
  159.29 + * This file is available under and governed by the GNU General Public
  159.30 + * License version 2 only, as published by the Free Software Foundation.
  159.31 + * However, the following notice accompanied the original version of this
  159.32 + * file:
  159.33 + *
  159.34 + * Written by Doug Lea and Josh Bloch with assistance from members of JCP
  159.35 + * JSR-166 Expert Group and released to the public domain, as explained at
  159.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  159.37 + */
  159.38 +
  159.39 +package java.util;
  159.40 +
  159.41 +/**
  159.42 + * A {@link SortedSet} extended with navigation methods reporting
  159.43 + * closest matches for given search targets. Methods {@code lower},
  159.44 + * {@code floor}, {@code ceiling}, and {@code higher} return elements
  159.45 + * respectively less than, less than or equal, greater than or equal,
  159.46 + * and greater than a given element, returning {@code null} if there
  159.47 + * is no such element.  A {@code NavigableSet} may be accessed and
  159.48 + * traversed in either ascending or descending order.  The {@code
  159.49 + * descendingSet} method returns a view of the set with the senses of
  159.50 + * all relational and directional methods inverted. The performance of
  159.51 + * ascending operations and views is likely to be faster than that of
  159.52 + * descending ones.  This interface additionally defines methods
  159.53 + * {@code pollFirst} and {@code pollLast} that return and remove the
  159.54 + * lowest and highest element, if one exists, else returning {@code
  159.55 + * null}.  Methods {@code subSet}, {@code headSet},
  159.56 + * and {@code tailSet} differ from the like-named {@code
  159.57 + * SortedSet} methods in accepting additional arguments describing
  159.58 + * whether lower and upper bounds are inclusive versus exclusive.
  159.59 + * Subsets of any {@code NavigableSet} must implement the {@code
  159.60 + * NavigableSet} interface.
  159.61 + *
  159.62 + * <p> The return values of navigation methods may be ambiguous in
  159.63 + * implementations that permit {@code null} elements. However, even
  159.64 + * in this case the result can be disambiguated by checking
  159.65 + * {@code contains(null)}. To avoid such issues, implementations of
  159.66 + * this interface are encouraged to <em>not</em> permit insertion of
  159.67 + * {@code null} elements. (Note that sorted sets of {@link
  159.68 + * Comparable} elements intrinsically do not permit {@code null}.)
  159.69 + *
  159.70 + * <p>Methods
  159.71 + * {@link #subSet(Object, Object) subSet(E, E)},
  159.72 + * {@link #headSet(Object) headSet(E)}, and
  159.73 + * {@link #tailSet(Object) tailSet(E)}
  159.74 + * are specified to return {@code SortedSet} to allow existing
  159.75 + * implementations of {@code SortedSet} to be compatibly retrofitted to
  159.76 + * implement {@code NavigableSet}, but extensions and implementations
  159.77 + * of this interface are encouraged to override these methods to return
  159.78 + * {@code NavigableSet}.
  159.79 + *
  159.80 + * <p>This interface is a member of the
  159.81 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  159.82 + * Java Collections Framework</a>.
  159.83 + *
  159.84 + * @author Doug Lea
  159.85 + * @author Josh Bloch
  159.86 + * @param <E> the type of elements maintained by this set
  159.87 + * @since 1.6
  159.88 + */
  159.89 +public interface NavigableSet<E> extends SortedSet<E> {
  159.90 +    /**
  159.91 +     * Returns the greatest element in this set strictly less than the
  159.92 +     * given element, or {@code null} if there is no such element.
  159.93 +     *
  159.94 +     * @param e the value to match
  159.95 +     * @return the greatest element less than {@code e},
  159.96 +     *         or {@code null} if there is no such element
  159.97 +     * @throws ClassCastException if the specified element cannot be
  159.98 +     *         compared with the elements currently in the set
  159.99 +     * @throws NullPointerException if the specified element is null
 159.100 +     *         and this set does not permit null elements
 159.101 +     */
 159.102 +    E lower(E e);
 159.103 +
 159.104 +    /**
 159.105 +     * Returns the greatest element in this set less than or equal to
 159.106 +     * the given element, or {@code null} if there is no such element.
 159.107 +     *
 159.108 +     * @param e the value to match
 159.109 +     * @return the greatest element less than or equal to {@code e},
 159.110 +     *         or {@code null} if there is no such element
 159.111 +     * @throws ClassCastException if the specified element cannot be
 159.112 +     *         compared with the elements currently in the set
 159.113 +     * @throws NullPointerException if the specified element is null
 159.114 +     *         and this set does not permit null elements
 159.115 +     */
 159.116 +    E floor(E e);
 159.117 +
 159.118 +    /**
 159.119 +     * Returns the least element in this set greater than or equal to
 159.120 +     * the given element, or {@code null} if there is no such element.
 159.121 +     *
 159.122 +     * @param e the value to match
 159.123 +     * @return the least element greater than or equal to {@code e},
 159.124 +     *         or {@code null} if there is no such element
 159.125 +     * @throws ClassCastException if the specified element cannot be
 159.126 +     *         compared with the elements currently in the set
 159.127 +     * @throws NullPointerException if the specified element is null
 159.128 +     *         and this set does not permit null elements
 159.129 +     */
 159.130 +    E ceiling(E e);
 159.131 +
 159.132 +    /**
 159.133 +     * Returns the least element in this set strictly greater than the
 159.134 +     * given element, or {@code null} if there is no such element.
 159.135 +     *
 159.136 +     * @param e the value to match
 159.137 +     * @return the least element greater than {@code e},
 159.138 +     *         or {@code null} if there is no such element
 159.139 +     * @throws ClassCastException if the specified element cannot be
 159.140 +     *         compared with the elements currently in the set
 159.141 +     * @throws NullPointerException if the specified element is null
 159.142 +     *         and this set does not permit null elements
 159.143 +     */
 159.144 +    E higher(E e);
 159.145 +
 159.146 +    /**
 159.147 +     * Retrieves and removes the first (lowest) element,
 159.148 +     * or returns {@code null} if this set is empty.
 159.149 +     *
 159.150 +     * @return the first element, or {@code null} if this set is empty
 159.151 +     */
 159.152 +    E pollFirst();
 159.153 +
 159.154 +    /**
 159.155 +     * Retrieves and removes the last (highest) element,
 159.156 +     * or returns {@code null} if this set is empty.
 159.157 +     *
 159.158 +     * @return the last element, or {@code null} if this set is empty
 159.159 +     */
 159.160 +    E pollLast();
 159.161 +
 159.162 +    /**
 159.163 +     * Returns an iterator over the elements in this set, in ascending order.
 159.164 +     *
 159.165 +     * @return an iterator over the elements in this set, in ascending order
 159.166 +     */
 159.167 +    Iterator<E> iterator();
 159.168 +
 159.169 +    /**
 159.170 +     * Returns a reverse order view of the elements contained in this set.
 159.171 +     * The descending set is backed by this set, so changes to the set are
 159.172 +     * reflected in the descending set, and vice-versa.  If either set is
 159.173 +     * modified while an iteration over either set is in progress (except
 159.174 +     * through the iterator's own {@code remove} operation), the results of
 159.175 +     * the iteration are undefined.
 159.176 +     *
 159.177 +     * <p>The returned set has an ordering equivalent to
 159.178 +     * <tt>{@link Collections#reverseOrder(Comparator) Collections.reverseOrder}(comparator())</tt>.
 159.179 +     * The expression {@code s.descendingSet().descendingSet()} returns a
 159.180 +     * view of {@code s} essentially equivalent to {@code s}.
 159.181 +     *
 159.182 +     * @return a reverse order view of this set
 159.183 +     */
 159.184 +    NavigableSet<E> descendingSet();
 159.185 +
 159.186 +    /**
 159.187 +     * Returns an iterator over the elements in this set, in descending order.
 159.188 +     * Equivalent in effect to {@code descendingSet().iterator()}.
 159.189 +     *
 159.190 +     * @return an iterator over the elements in this set, in descending order
 159.191 +     */
 159.192 +    Iterator<E> descendingIterator();
 159.193 +
 159.194 +    /**
 159.195 +     * Returns a view of the portion of this set whose elements range from
 159.196 +     * {@code fromElement} to {@code toElement}.  If {@code fromElement} and
 159.197 +     * {@code toElement} are equal, the returned set is empty unless {@code
 159.198 +     * fromInclusive} and {@code toInclusive} are both true.  The returned set
 159.199 +     * is backed by this set, so changes in the returned set are reflected in
 159.200 +     * this set, and vice-versa.  The returned set supports all optional set
 159.201 +     * operations that this set supports.
 159.202 +     *
 159.203 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 159.204 +     * on an attempt to insert an element outside its range.
 159.205 +     *
 159.206 +     * @param fromElement low endpoint of the returned set
 159.207 +     * @param fromInclusive {@code true} if the low endpoint
 159.208 +     *        is to be included in the returned view
 159.209 +     * @param toElement high endpoint of the returned set
 159.210 +     * @param toInclusive {@code true} if the high endpoint
 159.211 +     *        is to be included in the returned view
 159.212 +     * @return a view of the portion of this set whose elements range from
 159.213 +     *         {@code fromElement}, inclusive, to {@code toElement}, exclusive
 159.214 +     * @throws ClassCastException if {@code fromElement} and
 159.215 +     *         {@code toElement} cannot be compared to one another using this
 159.216 +     *         set's comparator (or, if the set has no comparator, using
 159.217 +     *         natural ordering).  Implementations may, but are not required
 159.218 +     *         to, throw this exception if {@code fromElement} or
 159.219 +     *         {@code toElement} cannot be compared to elements currently in
 159.220 +     *         the set.
 159.221 +     * @throws NullPointerException if {@code fromElement} or
 159.222 +     *         {@code toElement} is null and this set does
 159.223 +     *         not permit null elements
 159.224 +     * @throws IllegalArgumentException if {@code fromElement} is
 159.225 +     *         greater than {@code toElement}; or if this set itself
 159.226 +     *         has a restricted range, and {@code fromElement} or
 159.227 +     *         {@code toElement} lies outside the bounds of the range.
 159.228 +     */
 159.229 +    NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
 159.230 +                           E toElement,   boolean toInclusive);
 159.231 +
 159.232 +    /**
 159.233 +     * Returns a view of the portion of this set whose elements are less than
 159.234 +     * (or equal to, if {@code inclusive} is true) {@code toElement}.  The
 159.235 +     * returned set is backed by this set, so changes in the returned set are
 159.236 +     * reflected in this set, and vice-versa.  The returned set supports all
 159.237 +     * optional set operations that this set supports.
 159.238 +     *
 159.239 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 159.240 +     * on an attempt to insert an element outside its range.
 159.241 +     *
 159.242 +     * @param toElement high endpoint of the returned set
 159.243 +     * @param inclusive {@code true} if the high endpoint
 159.244 +     *        is to be included in the returned view
 159.245 +     * @return a view of the portion of this set whose elements are less than
 159.246 +     *         (or equal to, if {@code inclusive} is true) {@code toElement}
 159.247 +     * @throws ClassCastException if {@code toElement} is not compatible
 159.248 +     *         with this set's comparator (or, if the set has no comparator,
 159.249 +     *         if {@code toElement} does not implement {@link Comparable}).
 159.250 +     *         Implementations may, but are not required to, throw this
 159.251 +     *         exception if {@code toElement} cannot be compared to elements
 159.252 +     *         currently in the set.
 159.253 +     * @throws NullPointerException if {@code toElement} is null and
 159.254 +     *         this set does not permit null elements
 159.255 +     * @throws IllegalArgumentException if this set itself has a
 159.256 +     *         restricted range, and {@code toElement} lies outside the
 159.257 +     *         bounds of the range
 159.258 +     */
 159.259 +    NavigableSet<E> headSet(E toElement, boolean inclusive);
 159.260 +
 159.261 +    /**
 159.262 +     * Returns a view of the portion of this set whose elements are greater
 159.263 +     * than (or equal to, if {@code inclusive} is true) {@code fromElement}.
 159.264 +     * The returned set is backed by this set, so changes in the returned set
 159.265 +     * are reflected in this set, and vice-versa.  The returned set supports
 159.266 +     * all optional set operations that this set supports.
 159.267 +     *
 159.268 +     * <p>The returned set will throw an {@code IllegalArgumentException}
 159.269 +     * on an attempt to insert an element outside its range.
 159.270 +     *
 159.271 +     * @param fromElement low endpoint of the returned set
 159.272 +     * @param inclusive {@code true} if the low endpoint
 159.273 +     *        is to be included in the returned view
 159.274 +     * @return a view of the portion of this set whose elements are greater
 159.275 +     *         than or equal to {@code fromElement}
 159.276 +     * @throws ClassCastException if {@code fromElement} is not compatible
 159.277 +     *         with this set's comparator (or, if the set has no comparator,
 159.278 +     *         if {@code fromElement} does not implement {@link Comparable}).
 159.279 +     *         Implementations may, but are not required to, throw this
 159.280 +     *         exception if {@code fromElement} cannot be compared to elements
 159.281 +     *         currently in the set.
 159.282 +     * @throws NullPointerException if {@code fromElement} is null
 159.283 +     *         and this set does not permit null elements
 159.284 +     * @throws IllegalArgumentException if this set itself has a
 159.285 +     *         restricted range, and {@code fromElement} lies outside the
 159.286 +     *         bounds of the range
 159.287 +     */
 159.288 +    NavigableSet<E> tailSet(E fromElement, boolean inclusive);
 159.289 +
 159.290 +    /**
 159.291 +     * {@inheritDoc}
 159.292 +     *
 159.293 +     * <p>Equivalent to {@code subSet(fromElement, true, toElement, false)}.
 159.294 +     *
 159.295 +     * @throws ClassCastException       {@inheritDoc}
 159.296 +     * @throws NullPointerException     {@inheritDoc}
 159.297 +     * @throws IllegalArgumentException {@inheritDoc}
 159.298 +     */
 159.299 +    SortedSet<E> subSet(E fromElement, E toElement);
 159.300 +
 159.301 +    /**
 159.302 +     * {@inheritDoc}
 159.303 +     *
 159.304 +     * <p>Equivalent to {@code headSet(toElement, false)}.
 159.305 +     *
 159.306 +     * @throws ClassCastException       {@inheritDoc}
 159.307 +     * @throws NullPointerException     {@inheritDoc}
 159.308 +     * @throws IllegalArgumentException {@inheritDoc}
 159.309 +na     */
 159.310 +    SortedSet<E> headSet(E toElement);
 159.311 +
 159.312 +    /**
 159.313 +     * {@inheritDoc}
 159.314 +     *
 159.315 +     * <p>Equivalent to {@code tailSet(fromElement, true)}.
 159.316 +     *
 159.317 +     * @throws ClassCastException       {@inheritDoc}
 159.318 +     * @throws NullPointerException     {@inheritDoc}
 159.319 +     * @throws IllegalArgumentException {@inheritDoc}
 159.320 +     */
 159.321 +    SortedSet<E> tailSet(E fromElement);
 159.322 +}
   160.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   160.2 +++ b/rt/emul/compact/src/main/java/java/util/RegularEnumSet.java	Mon Oct 07 14:20:58 2013 +0200
   160.3 @@ -0,0 +1,303 @@
   160.4 +/*
   160.5 + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
   160.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   160.7 + *
   160.8 + * This code is free software; you can redistribute it and/or modify it
   160.9 + * under the terms of the GNU General Public License version 2 only, as
  160.10 + * published by the Free Software Foundation.  Oracle designates this
  160.11 + * particular file as subject to the "Classpath" exception as provided
  160.12 + * by Oracle in the LICENSE file that accompanied this code.
  160.13 + *
  160.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  160.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  160.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  160.17 + * version 2 for more details (a copy is included in the LICENSE file that
  160.18 + * accompanied this code).
  160.19 + *
  160.20 + * You should have received a copy of the GNU General Public License version
  160.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  160.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  160.23 + *
  160.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  160.25 + * or visit www.oracle.com if you need additional information or have any
  160.26 + * questions.
  160.27 + */
  160.28 +
  160.29 +package java.util;
  160.30 +
  160.31 +/**
  160.32 + * Private implementation class for EnumSet, for "regular sized" enum types
  160.33 + * (i.e., those with 64 or fewer enum constants).
  160.34 + *
  160.35 + * @author Josh Bloch
  160.36 + * @since 1.5
  160.37 + * @serial exclude
  160.38 + */
  160.39 +class RegularEnumSet<E extends Enum<E>> extends EnumSet<E> {
  160.40 +    private static final long serialVersionUID = 3411599620347842686L;
  160.41 +    /**
  160.42 +     * Bit vector representation of this set.  The 2^k bit indicates the
  160.43 +     * presence of universe[k] in this set.
  160.44 +     */
  160.45 +    private long elements = 0L;
  160.46 +
  160.47 +    RegularEnumSet(Class<E>elementType, Enum[] universe) {
  160.48 +        super(elementType, universe);
  160.49 +    }
  160.50 +
  160.51 +    void addRange(E from, E to) {
  160.52 +        elements = (-1L >>>  (from.ordinal() - to.ordinal() - 1)) << from.ordinal();
  160.53 +    }
  160.54 +
  160.55 +    void addAll() {
  160.56 +        if (universe.length != 0)
  160.57 +            elements = -1L >>> -universe.length;
  160.58 +    }
  160.59 +
  160.60 +    void complement() {
  160.61 +        if (universe.length != 0) {
  160.62 +            elements = ~elements;
  160.63 +            elements &= -1L >>> -universe.length;  // Mask unused bits
  160.64 +        }
  160.65 +    }
  160.66 +
  160.67 +    /**
  160.68 +     * Returns an iterator over the elements contained in this set.  The
  160.69 +     * iterator traverses the elements in their <i>natural order</i> (which is
  160.70 +     * the order in which the enum constants are declared). The returned
  160.71 +     * Iterator is a "snapshot" iterator that will never throw {@link
  160.72 +     * ConcurrentModificationException}; the elements are traversed as they
  160.73 +     * existed when this call was invoked.
  160.74 +     *
  160.75 +     * @return an iterator over the elements contained in this set
  160.76 +     */
  160.77 +    public Iterator<E> iterator() {
  160.78 +        return new EnumSetIterator<>();
  160.79 +    }
  160.80 +
  160.81 +    private class EnumSetIterator<E extends Enum<E>> implements Iterator<E> {
  160.82 +        /**
  160.83 +         * A bit vector representing the elements in the set not yet
  160.84 +         * returned by this iterator.
  160.85 +         */
  160.86 +        long unseen;
  160.87 +
  160.88 +        /**
  160.89 +         * The bit representing the last element returned by this iterator
  160.90 +         * but not removed, or zero if no such element exists.
  160.91 +         */
  160.92 +        long lastReturned = 0;
  160.93 +
  160.94 +        EnumSetIterator() {
  160.95 +            unseen = elements;
  160.96 +        }
  160.97 +
  160.98 +        public boolean hasNext() {
  160.99 +            return unseen != 0;
 160.100 +        }
 160.101 +
 160.102 +        public E next() {
 160.103 +            if (unseen == 0)
 160.104 +                throw new NoSuchElementException();
 160.105 +            lastReturned = unseen & -unseen;
 160.106 +            unseen -= lastReturned;
 160.107 +            return (E) universe[Long.numberOfTrailingZeros(lastReturned)];
 160.108 +        }
 160.109 +
 160.110 +        public void remove() {
 160.111 +            if (lastReturned == 0)
 160.112 +                throw new IllegalStateException();
 160.113 +            elements &= ~lastReturned;
 160.114 +            lastReturned = 0;
 160.115 +        }
 160.116 +    }
 160.117 +
 160.118 +    /**
 160.119 +     * Returns the number of elements in this set.
 160.120 +     *
 160.121 +     * @return the number of elements in this set
 160.122 +     */
 160.123 +    public int size() {
 160.124 +        return Long.bitCount(elements);
 160.125 +    }
 160.126 +
 160.127 +    /**
 160.128 +     * Returns <tt>true</tt> if this set contains no elements.
 160.129 +     *
 160.130 +     * @return <tt>true</tt> if this set contains no elements
 160.131 +     */
 160.132 +    public boolean isEmpty() {
 160.133 +        return elements == 0;
 160.134 +    }
 160.135 +
 160.136 +    /**
 160.137 +     * Returns <tt>true</tt> if this set contains the specified element.
 160.138 +     *
 160.139 +     * @param e element to be checked for containment in this collection
 160.140 +     * @return <tt>true</tt> if this set contains the specified element
 160.141 +     */
 160.142 +    public boolean contains(Object e) {
 160.143 +        if (e == null)
 160.144 +            return false;
 160.145 +        Class eClass = e.getClass();
 160.146 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 160.147 +            return false;
 160.148 +
 160.149 +        return (elements & (1L << ((Enum)e).ordinal())) != 0;
 160.150 +    }
 160.151 +
 160.152 +    // Modification Operations
 160.153 +
 160.154 +    /**
 160.155 +     * Adds the specified element to this set if it is not already present.
 160.156 +     *
 160.157 +     * @param e element to be added to this set
 160.158 +     * @return <tt>true</tt> if the set changed as a result of the call
 160.159 +     *
 160.160 +     * @throws NullPointerException if <tt>e</tt> is null
 160.161 +     */
 160.162 +    public boolean add(E e) {
 160.163 +        typeCheck(e);
 160.164 +
 160.165 +        long oldElements = elements;
 160.166 +        elements |= (1L << ((Enum)e).ordinal());
 160.167 +        return elements != oldElements;
 160.168 +    }
 160.169 +
 160.170 +    /**
 160.171 +     * Removes the specified element from this set if it is present.
 160.172 +     *
 160.173 +     * @param e element to be removed from this set, if present
 160.174 +     * @return <tt>true</tt> if the set contained the specified element
 160.175 +     */
 160.176 +    public boolean remove(Object e) {
 160.177 +        if (e == null)
 160.178 +            return false;
 160.179 +        Class eClass = e.getClass();
 160.180 +        if (eClass != elementType && eClass.getSuperclass() != elementType)
 160.181 +            return false;
 160.182 +
 160.183 +        long oldElements = elements;
 160.184 +        elements &= ~(1L << ((Enum)e).ordinal());
 160.185 +        return elements != oldElements;
 160.186 +    }
 160.187 +
 160.188 +    // Bulk Operations
 160.189 +
 160.190 +    /**
 160.191 +     * Returns <tt>true</tt> if this set contains all of the elements
 160.192 +     * in the specified collection.
 160.193 +     *
 160.194 +     * @param c collection to be checked for containment in this set
 160.195 +     * @return <tt>true</tt> if this set contains all of the elements
 160.196 +     *        in the specified collection
 160.197 +     * @throws NullPointerException if the specified collection is null
 160.198 +     */
 160.199 +    public boolean containsAll(Collection<?> c) {
 160.200 +        if (!(c instanceof RegularEnumSet))
 160.201 +            return super.containsAll(c);
 160.202 +
 160.203 +        RegularEnumSet es = (RegularEnumSet)c;
 160.204 +        if (es.elementType != elementType)
 160.205 +            return es.isEmpty();
 160.206 +
 160.207 +        return (es.elements & ~elements) == 0;
 160.208 +    }
 160.209 +
 160.210 +    /**
 160.211 +     * Adds all of the elements in the specified collection to this set.
 160.212 +     *
 160.213 +     * @param c collection whose elements are to be added to this set
 160.214 +     * @return <tt>true</tt> if this set changed as a result of the call
 160.215 +     * @throws NullPointerException if the specified collection or any
 160.216 +     *     of its elements are null
 160.217 +     */
 160.218 +    public boolean addAll(Collection<? extends E> c) {
 160.219 +        if (!(c instanceof RegularEnumSet))
 160.220 +            return super.addAll(c);
 160.221 +
 160.222 +        RegularEnumSet es = (RegularEnumSet)c;
 160.223 +        if (es.elementType != elementType) {
 160.224 +            if (es.isEmpty())
 160.225 +                return false;
 160.226 +            else
 160.227 +                throw new ClassCastException(
 160.228 +                    es.elementType + " != " + elementType);
 160.229 +        }
 160.230 +
 160.231 +        long oldElements = elements;
 160.232 +        elements |= es.elements;
 160.233 +        return elements != oldElements;
 160.234 +    }
 160.235 +
 160.236 +    /**
 160.237 +     * Removes from this set all of its elements that are contained in
 160.238 +     * the specified collection.
 160.239 +     *
 160.240 +     * @param c elements to be removed from this set
 160.241 +     * @return <tt>true</tt> if this set changed as a result of the call
 160.242 +     * @throws NullPointerException if the specified collection is null
 160.243 +     */
 160.244 +    public boolean removeAll(Collection<?> c) {
 160.245 +        if (!(c instanceof RegularEnumSet))
 160.246 +            return super.removeAll(c);
 160.247 +
 160.248 +        RegularEnumSet es = (RegularEnumSet)c;
 160.249 +        if (es.elementType != elementType)
 160.250 +            return false;
 160.251 +
 160.252 +        long oldElements = elements;
 160.253 +        elements &= ~es.elements;
 160.254 +        return elements != oldElements;
 160.255 +    }
 160.256 +
 160.257 +    /**
 160.258 +     * Retains only the elements in this set that are contained in the
 160.259 +     * specified collection.
 160.260 +     *
 160.261 +     * @param c elements to be retained in this set
 160.262 +     * @return <tt>true</tt> if this set changed as a result of the call
 160.263 +     * @throws NullPointerException if the specified collection is null
 160.264 +     */
 160.265 +    public boolean retainAll(Collection<?> c) {
 160.266 +        if (!(c instanceof RegularEnumSet))
 160.267 +            return super.retainAll(c);
 160.268 +
 160.269 +        RegularEnumSet<?> es = (RegularEnumSet<?>)c;
 160.270 +        if (es.elementType != elementType) {
 160.271 +            boolean changed = (elements != 0);
 160.272 +            elements = 0;
 160.273 +            return changed;
 160.274 +        }
 160.275 +
 160.276 +        long oldElements = elements;
 160.277 +        elements &= es.elements;
 160.278 +        return elements != oldElements;
 160.279 +    }
 160.280 +
 160.281 +    /**
 160.282 +     * Removes all of the elements from this set.
 160.283 +     */
 160.284 +    public void clear() {
 160.285 +        elements = 0;
 160.286 +    }
 160.287 +
 160.288 +    /**
 160.289 +     * Compares the specified object with this set for equality.  Returns
 160.290 +     * <tt>true</tt> if the given object is also a set, the two sets have
 160.291 +     * the same size, and every member of the given set is contained in
 160.292 +     * this set.
 160.293 +     *
 160.294 +     * @param e object to be compared for equality with this set
 160.295 +     * @return <tt>true</tt> if the specified object is equal to this set
 160.296 +     */
 160.297 +    public boolean equals(Object o) {
 160.298 +        if (!(o instanceof RegularEnumSet))
 160.299 +            return super.equals(o);
 160.300 +
 160.301 +        RegularEnumSet es = (RegularEnumSet)o;
 160.302 +        if (es.elementType != elementType)
 160.303 +            return elements == 0 && es.elements == 0;
 160.304 +        return es.elements == elements;
 160.305 +    }
 160.306 +}
   161.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   161.2 +++ b/rt/emul/compact/src/main/java/java/util/TreeMap.java	Mon Oct 07 14:20:58 2013 +0200
   161.3 @@ -0,0 +1,2442 @@
   161.4 +/*
   161.5 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
   161.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   161.7 + *
   161.8 + * This code is free software; you can redistribute it and/or modify it
   161.9 + * under the terms of the GNU General Public License version 2 only, as
  161.10 + * published by the Free Software Foundation.  Oracle designates this
  161.11 + * particular file as subject to the "Classpath" exception as provided
  161.12 + * by Oracle in the LICENSE file that accompanied this code.
  161.13 + *
  161.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  161.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  161.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  161.17 + * version 2 for more details (a copy is included in the LICENSE file that
  161.18 + * accompanied this code).
  161.19 + *
  161.20 + * You should have received a copy of the GNU General Public License version
  161.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  161.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  161.23 + *
  161.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  161.25 + * or visit www.oracle.com if you need additional information or have any
  161.26 + * questions.
  161.27 + */
  161.28 +
  161.29 +package java.util;
  161.30 +
  161.31 +/**
  161.32 + * A Red-Black tree based {@link NavigableMap} implementation.
  161.33 + * The map is sorted according to the {@linkplain Comparable natural
  161.34 + * ordering} of its keys, or by a {@link Comparator} provided at map
  161.35 + * creation time, depending on which constructor is used.
  161.36 + *
  161.37 + * <p>This implementation provides guaranteed log(n) time cost for the
  161.38 + * {@code containsKey}, {@code get}, {@code put} and {@code remove}
  161.39 + * operations.  Algorithms are adaptations of those in Cormen, Leiserson, and
  161.40 + * Rivest's <em>Introduction to Algorithms</em>.
  161.41 + *
  161.42 + * <p>Note that the ordering maintained by a tree map, like any sorted map, and
  161.43 + * whether or not an explicit comparator is provided, must be <em>consistent
  161.44 + * with {@code equals}</em> if this sorted map is to correctly implement the
  161.45 + * {@code Map} interface.  (See {@code Comparable} or {@code Comparator} for a
  161.46 + * precise definition of <em>consistent with equals</em>.)  This is so because
  161.47 + * the {@code Map} interface is defined in terms of the {@code equals}
  161.48 + * operation, but a sorted map performs all key comparisons using its {@code
  161.49 + * compareTo} (or {@code compare}) method, so two keys that are deemed equal by
  161.50 + * this method are, from the standpoint of the sorted map, equal.  The behavior
  161.51 + * of a sorted map <em>is</em> well-defined even if its ordering is
  161.52 + * inconsistent with {@code equals}; it just fails to obey the general contract
  161.53 + * of the {@code Map} interface.
  161.54 + *
  161.55 + * <p><strong>Note that this implementation is not synchronized.</strong>
  161.56 + * If multiple threads access a map concurrently, and at least one of the
  161.57 + * threads modifies the map structurally, it <em>must</em> be synchronized
  161.58 + * externally.  (A structural modification is any operation that adds or
  161.59 + * deletes one or more mappings; merely changing the value associated
  161.60 + * with an existing key is not a structural modification.)  This is
  161.61 + * typically accomplished by synchronizing on some object that naturally
  161.62 + * encapsulates the map.
  161.63 + * If no such object exists, the map should be "wrapped" using the
  161.64 + * {@link Collections#synchronizedSortedMap Collections.synchronizedSortedMap}
  161.65 + * method.  This is best done at creation time, to prevent accidental
  161.66 + * unsynchronized access to the map: <pre>
  161.67 + *   SortedMap m = Collections.synchronizedSortedMap(new TreeMap(...));</pre>
  161.68 + *
  161.69 + * <p>The iterators returned by the {@code iterator} method of the collections
  161.70 + * returned by all of this class's "collection view methods" are
  161.71 + * <em>fail-fast</em>: if the map is structurally modified at any time after
  161.72 + * the iterator is created, in any way except through the iterator's own
  161.73 + * {@code remove} method, the iterator will throw a {@link
  161.74 + * ConcurrentModificationException}.  Thus, in the face of concurrent
  161.75 + * modification, the iterator fails quickly and cleanly, rather than risking
  161.76 + * arbitrary, non-deterministic behavior at an undetermined time in the future.
  161.77 + *
  161.78 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  161.79 + * as it is, generally speaking, impossible to make any hard guarantees in the
  161.80 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
  161.81 + * throw {@code ConcurrentModificationException} on a best-effort basis.
  161.82 + * Therefore, it would be wrong to write a program that depended on this
  161.83 + * exception for its correctness:   <em>the fail-fast behavior of iterators
  161.84 + * should be used only to detect bugs.</em>
  161.85 + *
  161.86 + * <p>All {@code Map.Entry} pairs returned by methods in this class
  161.87 + * and its views represent snapshots of mappings at the time they were
  161.88 + * produced. They do <strong>not</strong> support the {@code Entry.setValue}
  161.89 + * method. (Note however that it is possible to change mappings in the
  161.90 + * associated map using {@code put}.)
  161.91 + *
  161.92 + * <p>This class is a member of the
  161.93 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  161.94 + * Java Collections Framework</a>.
  161.95 + *
  161.96 + * @param <K> the type of keys maintained by this map
  161.97 + * @param <V> the type of mapped values
  161.98 + *
  161.99 + * @author  Josh Bloch and Doug Lea
 161.100 + * @see Map
 161.101 + * @see HashMap
 161.102 + * @see Hashtable
 161.103 + * @see Comparable
 161.104 + * @see Comparator
 161.105 + * @see Collection
 161.106 + * @since 1.2
 161.107 + */
 161.108 +
 161.109 +public class TreeMap<K,V>
 161.110 +    extends AbstractMap<K,V>
 161.111 +    implements NavigableMap<K,V>, Cloneable, java.io.Serializable
 161.112 +{
 161.113 +    /**
 161.114 +     * The comparator used to maintain order in this tree map, or
 161.115 +     * null if it uses the natural ordering of its keys.
 161.116 +     *
 161.117 +     * @serial
 161.118 +     */
 161.119 +    private final Comparator<? super K> comparator;
 161.120 +
 161.121 +    private transient Entry<K,V> root = null;
 161.122 +
 161.123 +    /**
 161.124 +     * The number of entries in the tree
 161.125 +     */
 161.126 +    private transient int size = 0;
 161.127 +
 161.128 +    /**
 161.129 +     * The number of structural modifications to the tree.
 161.130 +     */
 161.131 +    private transient int modCount = 0;
 161.132 +
 161.133 +    /**
 161.134 +     * Constructs a new, empty tree map, using the natural ordering of its
 161.135 +     * keys.  All keys inserted into the map must implement the {@link
 161.136 +     * Comparable} interface.  Furthermore, all such keys must be
 161.137 +     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
 161.138 +     * a {@code ClassCastException} for any keys {@code k1} and
 161.139 +     * {@code k2} in the map.  If the user attempts to put a key into the
 161.140 +     * map that violates this constraint (for example, the user attempts to
 161.141 +     * put a string key into a map whose keys are integers), the
 161.142 +     * {@code put(Object key, Object value)} call will throw a
 161.143 +     * {@code ClassCastException}.
 161.144 +     */
 161.145 +    public TreeMap() {
 161.146 +        comparator = null;
 161.147 +    }
 161.148 +
 161.149 +    /**
 161.150 +     * Constructs a new, empty tree map, ordered according to the given
 161.151 +     * comparator.  All keys inserted into the map must be <em>mutually
 161.152 +     * comparable</em> by the given comparator: {@code comparator.compare(k1,
 161.153 +     * k2)} must not throw a {@code ClassCastException} for any keys
 161.154 +     * {@code k1} and {@code k2} in the map.  If the user attempts to put
 161.155 +     * a key into the map that violates this constraint, the {@code put(Object
 161.156 +     * key, Object value)} call will throw a
 161.157 +     * {@code ClassCastException}.
 161.158 +     *
 161.159 +     * @param comparator the comparator that will be used to order this map.
 161.160 +     *        If {@code null}, the {@linkplain Comparable natural
 161.161 +     *        ordering} of the keys will be used.
 161.162 +     */
 161.163 +    public TreeMap(Comparator<? super K> comparator) {
 161.164 +        this.comparator = comparator;
 161.165 +    }
 161.166 +
 161.167 +    /**
 161.168 +     * Constructs a new tree map containing the same mappings as the given
 161.169 +     * map, ordered according to the <em>natural ordering</em> of its keys.
 161.170 +     * All keys inserted into the new map must implement the {@link
 161.171 +     * Comparable} interface.  Furthermore, all such keys must be
 161.172 +     * <em>mutually comparable</em>: {@code k1.compareTo(k2)} must not throw
 161.173 +     * a {@code ClassCastException} for any keys {@code k1} and
 161.174 +     * {@code k2} in the map.  This method runs in n*log(n) time.
 161.175 +     *
 161.176 +     * @param  m the map whose mappings are to be placed in this map
 161.177 +     * @throws ClassCastException if the keys in m are not {@link Comparable},
 161.178 +     *         or are not mutually comparable
 161.179 +     * @throws NullPointerException if the specified map is null
 161.180 +     */
 161.181 +    public TreeMap(Map<? extends K, ? extends V> m) {
 161.182 +        comparator = null;
 161.183 +        putAll(m);
 161.184 +    }
 161.185 +
 161.186 +    /**
 161.187 +     * Constructs a new tree map containing the same mappings and
 161.188 +     * using the same ordering as the specified sorted map.  This
 161.189 +     * method runs in linear time.
 161.190 +     *
 161.191 +     * @param  m the sorted map whose mappings are to be placed in this map,
 161.192 +     *         and whose comparator is to be used to sort this map
 161.193 +     * @throws NullPointerException if the specified map is null
 161.194 +     */
 161.195 +    public TreeMap(SortedMap<K, ? extends V> m) {
 161.196 +        comparator = m.comparator();
 161.197 +        try {
 161.198 +            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
 161.199 +        } catch (java.io.IOException cannotHappen) {
 161.200 +        } catch (ClassNotFoundException cannotHappen) {
 161.201 +        }
 161.202 +    }
 161.203 +
 161.204 +
 161.205 +    // Query Operations
 161.206 +
 161.207 +    /**
 161.208 +     * Returns the number of key-value mappings in this map.
 161.209 +     *
 161.210 +     * @return the number of key-value mappings in this map
 161.211 +     */
 161.212 +    public int size() {
 161.213 +        return size;
 161.214 +    }
 161.215 +
 161.216 +    /**
 161.217 +     * Returns {@code true} if this map contains a mapping for the specified
 161.218 +     * key.
 161.219 +     *
 161.220 +     * @param key key whose presence in this map is to be tested
 161.221 +     * @return {@code true} if this map contains a mapping for the
 161.222 +     *         specified key
 161.223 +     * @throws ClassCastException if the specified key cannot be compared
 161.224 +     *         with the keys currently in the map
 161.225 +     * @throws NullPointerException if the specified key is null
 161.226 +     *         and this map uses natural ordering, or its comparator
 161.227 +     *         does not permit null keys
 161.228 +     */
 161.229 +    public boolean containsKey(Object key) {
 161.230 +        return getEntry(key) != null;
 161.231 +    }
 161.232 +
 161.233 +    /**
 161.234 +     * Returns {@code true} if this map maps one or more keys to the
 161.235 +     * specified value.  More formally, returns {@code true} if and only if
 161.236 +     * this map contains at least one mapping to a value {@code v} such
 161.237 +     * that {@code (value==null ? v==null : value.equals(v))}.  This
 161.238 +     * operation will probably require time linear in the map size for
 161.239 +     * most implementations.
 161.240 +     *
 161.241 +     * @param value value whose presence in this map is to be tested
 161.242 +     * @return {@code true} if a mapping to {@code value} exists;
 161.243 +     *         {@code false} otherwise
 161.244 +     * @since 1.2
 161.245 +     */
 161.246 +    public boolean containsValue(Object value) {
 161.247 +        for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e))
 161.248 +            if (valEquals(value, e.value))
 161.249 +                return true;
 161.250 +        return false;
 161.251 +    }
 161.252 +
 161.253 +    /**
 161.254 +     * Returns the value to which the specified key is mapped,
 161.255 +     * or {@code null} if this map contains no mapping for the key.
 161.256 +     *
 161.257 +     * <p>More formally, if this map contains a mapping from a key
 161.258 +     * {@code k} to a value {@code v} such that {@code key} compares
 161.259 +     * equal to {@code k} according to the map's ordering, then this
 161.260 +     * method returns {@code v}; otherwise it returns {@code null}.
 161.261 +     * (There can be at most one such mapping.)
 161.262 +     *
 161.263 +     * <p>A return value of {@code null} does not <em>necessarily</em>
 161.264 +     * indicate that the map contains no mapping for the key; it's also
 161.265 +     * possible that the map explicitly maps the key to {@code null}.
 161.266 +     * The {@link #containsKey containsKey} operation may be used to
 161.267 +     * distinguish these two cases.
 161.268 +     *
 161.269 +     * @throws ClassCastException if the specified key cannot be compared
 161.270 +     *         with the keys currently in the map
 161.271 +     * @throws NullPointerException if the specified key is null
 161.272 +     *         and this map uses natural ordering, or its comparator
 161.273 +     *         does not permit null keys
 161.274 +     */
 161.275 +    public V get(Object key) {
 161.276 +        Entry<K,V> p = getEntry(key);
 161.277 +        return (p==null ? null : p.value);
 161.278 +    }
 161.279 +
 161.280 +    public Comparator<? super K> comparator() {
 161.281 +        return comparator;
 161.282 +    }
 161.283 +
 161.284 +    /**
 161.285 +     * @throws NoSuchElementException {@inheritDoc}
 161.286 +     */
 161.287 +    public K firstKey() {
 161.288 +        return key(getFirstEntry());
 161.289 +    }
 161.290 +
 161.291 +    /**
 161.292 +     * @throws NoSuchElementException {@inheritDoc}
 161.293 +     */
 161.294 +    public K lastKey() {
 161.295 +        return key(getLastEntry());
 161.296 +    }
 161.297 +
 161.298 +    /**
 161.299 +     * Copies all of the mappings from the specified map to this map.
 161.300 +     * These mappings replace any mappings that this map had for any
 161.301 +     * of the keys currently in the specified map.
 161.302 +     *
 161.303 +     * @param  map mappings to be stored in this map
 161.304 +     * @throws ClassCastException if the class of a key or value in
 161.305 +     *         the specified map prevents it from being stored in this map
 161.306 +     * @throws NullPointerException if the specified map is null or
 161.307 +     *         the specified map contains a null key and this map does not
 161.308 +     *         permit null keys
 161.309 +     */
 161.310 +    public void putAll(Map<? extends K, ? extends V> map) {
 161.311 +        int mapSize = map.size();
 161.312 +        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
 161.313 +            Comparator c = ((SortedMap)map).comparator();
 161.314 +            if (c == comparator || (c != null && c.equals(comparator))) {
 161.315 +                ++modCount;
 161.316 +                try {
 161.317 +                    buildFromSorted(mapSize, map.entrySet().iterator(),
 161.318 +                                    null, null);
 161.319 +                } catch (java.io.IOException cannotHappen) {
 161.320 +                } catch (ClassNotFoundException cannotHappen) {
 161.321 +                }
 161.322 +                return;
 161.323 +            }
 161.324 +        }
 161.325 +        super.putAll(map);
 161.326 +    }
 161.327 +
 161.328 +    /**
 161.329 +     * Returns this map's entry for the given key, or {@code null} if the map
 161.330 +     * does not contain an entry for the key.
 161.331 +     *
 161.332 +     * @return this map's entry for the given key, or {@code null} if the map
 161.333 +     *         does not contain an entry for the key
 161.334 +     * @throws ClassCastException if the specified key cannot be compared
 161.335 +     *         with the keys currently in the map
 161.336 +     * @throws NullPointerException if the specified key is null
 161.337 +     *         and this map uses natural ordering, or its comparator
 161.338 +     *         does not permit null keys
 161.339 +     */
 161.340 +    final Entry<K,V> getEntry(Object key) {
 161.341 +        // Offload comparator-based version for sake of performance
 161.342 +        if (comparator != null)
 161.343 +            return getEntryUsingComparator(key);
 161.344 +        if (key == null)
 161.345 +            throw new NullPointerException();
 161.346 +        Comparable<? super K> k = (Comparable<? super K>) key;
 161.347 +        Entry<K,V> p = root;
 161.348 +        while (p != null) {
 161.349 +            int cmp = k.compareTo(p.key);
 161.350 +            if (cmp < 0)
 161.351 +                p = p.left;
 161.352 +            else if (cmp > 0)
 161.353 +                p = p.right;
 161.354 +            else
 161.355 +                return p;
 161.356 +        }
 161.357 +        return null;
 161.358 +    }
 161.359 +
 161.360 +    /**
 161.361 +     * Version of getEntry using comparator. Split off from getEntry
 161.362 +     * for performance. (This is not worth doing for most methods,
 161.363 +     * that are less dependent on comparator performance, but is
 161.364 +     * worthwhile here.)
 161.365 +     */
 161.366 +    final Entry<K,V> getEntryUsingComparator(Object key) {
 161.367 +        K k = (K) key;
 161.368 +        Comparator<? super K> cpr = comparator;
 161.369 +        if (cpr != null) {
 161.370 +            Entry<K,V> p = root;
 161.371 +            while (p != null) {
 161.372 +                int cmp = cpr.compare(k, p.key);
 161.373 +                if (cmp < 0)
 161.374 +                    p = p.left;
 161.375 +                else if (cmp > 0)
 161.376 +                    p = p.right;
 161.377 +                else
 161.378 +                    return p;
 161.379 +            }
 161.380 +        }
 161.381 +        return null;
 161.382 +    }
 161.383 +
 161.384 +    /**
 161.385 +     * Gets the entry corresponding to the specified key; if no such entry
 161.386 +     * exists, returns the entry for the least key greater than the specified
 161.387 +     * key; if no such entry exists (i.e., the greatest key in the Tree is less
 161.388 +     * than the specified key), returns {@code null}.
 161.389 +     */
 161.390 +    final Entry<K,V> getCeilingEntry(K key) {
 161.391 +        Entry<K,V> p = root;
 161.392 +        while (p != null) {
 161.393 +            int cmp = compare(key, p.key);
 161.394 +            if (cmp < 0) {
 161.395 +                if (p.left != null)
 161.396 +                    p = p.left;
 161.397 +                else
 161.398 +                    return p;
 161.399 +            } else if (cmp > 0) {
 161.400 +                if (p.right != null) {
 161.401 +                    p = p.right;
 161.402 +                } else {
 161.403 +                    Entry<K,V> parent = p.parent;
 161.404 +                    Entry<K,V> ch = p;
 161.405 +                    while (parent != null && ch == parent.right) {
 161.406 +                        ch = parent;
 161.407 +                        parent = parent.parent;
 161.408 +                    }
 161.409 +                    return parent;
 161.410 +                }
 161.411 +            } else
 161.412 +                return p;
 161.413 +        }
 161.414 +        return null;
 161.415 +    }
 161.416 +
 161.417 +    /**
 161.418 +     * Gets the entry corresponding to the specified key; if no such entry
 161.419 +     * exists, returns the entry for the greatest key less than the specified
 161.420 +     * key; if no such entry exists, returns {@code null}.
 161.421 +     */
 161.422 +    final Entry<K,V> getFloorEntry(K key) {
 161.423 +        Entry<K,V> p = root;
 161.424 +        while (p != null) {
 161.425 +            int cmp = compare(key, p.key);
 161.426 +            if (cmp > 0) {
 161.427 +                if (p.right != null)
 161.428 +                    p = p.right;
 161.429 +                else
 161.430 +                    return p;
 161.431 +            } else if (cmp < 0) {
 161.432 +                if (p.left != null) {
 161.433 +                    p = p.left;
 161.434 +                } else {
 161.435 +                    Entry<K,V> parent = p.parent;
 161.436 +                    Entry<K,V> ch = p;
 161.437 +                    while (parent != null && ch == parent.left) {
 161.438 +                        ch = parent;
 161.439 +                        parent = parent.parent;
 161.440 +                    }
 161.441 +                    return parent;
 161.442 +                }
 161.443 +            } else
 161.444 +                return p;
 161.445 +
 161.446 +        }
 161.447 +        return null;
 161.448 +    }
 161.449 +
 161.450 +    /**
 161.451 +     * Gets the entry for the least key greater than the specified
 161.452 +     * key; if no such entry exists, returns the entry for the least
 161.453 +     * key greater than the specified key; if no such entry exists
 161.454 +     * returns {@code null}.
 161.455 +     */
 161.456 +    final Entry<K,V> getHigherEntry(K key) {
 161.457 +        Entry<K,V> p = root;
 161.458 +        while (p != null) {
 161.459 +            int cmp = compare(key, p.key);
 161.460 +            if (cmp < 0) {
 161.461 +                if (p.left != null)
 161.462 +                    p = p.left;
 161.463 +                else
 161.464 +                    return p;
 161.465 +            } else {
 161.466 +                if (p.right != null) {
 161.467 +                    p = p.right;
 161.468 +                } else {
 161.469 +                    Entry<K,V> parent = p.parent;
 161.470 +                    Entry<K,V> ch = p;
 161.471 +                    while (parent != null && ch == parent.right) {
 161.472 +                        ch = parent;
 161.473 +                        parent = parent.parent;
 161.474 +                    }
 161.475 +                    return parent;
 161.476 +                }
 161.477 +            }
 161.478 +        }
 161.479 +        return null;
 161.480 +    }
 161.481 +
 161.482 +    /**
 161.483 +     * Returns the entry for the greatest key less than the specified key; if
 161.484 +     * no such entry exists (i.e., the least key in the Tree is greater than
 161.485 +     * the specified key), returns {@code null}.
 161.486 +     */
 161.487 +    final Entry<K,V> getLowerEntry(K key) {
 161.488 +        Entry<K,V> p = root;
 161.489 +        while (p != null) {
 161.490 +            int cmp = compare(key, p.key);
 161.491 +            if (cmp > 0) {
 161.492 +                if (p.right != null)
 161.493 +                    p = p.right;
 161.494 +                else
 161.495 +                    return p;
 161.496 +            } else {
 161.497 +                if (p.left != null) {
 161.498 +                    p = p.left;
 161.499 +                } else {
 161.500 +                    Entry<K,V> parent = p.parent;
 161.501 +                    Entry<K,V> ch = p;
 161.502 +                    while (parent != null && ch == parent.left) {
 161.503 +                        ch = parent;
 161.504 +                        parent = parent.parent;
 161.505 +                    }
 161.506 +                    return parent;
 161.507 +                }
 161.508 +            }
 161.509 +        }
 161.510 +        return null;
 161.511 +    }
 161.512 +
 161.513 +    /**
 161.514 +     * Associates the specified value with the specified key in this map.
 161.515 +     * If the map previously contained a mapping for the key, the old
 161.516 +     * value is replaced.
 161.517 +     *
 161.518 +     * @param key key with which the specified value is to be associated
 161.519 +     * @param value value to be associated with the specified key
 161.520 +     *
 161.521 +     * @return the previous value associated with {@code key}, or
 161.522 +     *         {@code null} if there was no mapping for {@code key}.
 161.523 +     *         (A {@code null} return can also indicate that the map
 161.524 +     *         previously associated {@code null} with {@code key}.)
 161.525 +     * @throws ClassCastException if the specified key cannot be compared
 161.526 +     *         with the keys currently in the map
 161.527 +     * @throws NullPointerException if the specified key is null
 161.528 +     *         and this map uses natural ordering, or its comparator
 161.529 +     *         does not permit null keys
 161.530 +     */
 161.531 +    public V put(K key, V value) {
 161.532 +        Entry<K,V> t = root;
 161.533 +        if (t == null) {
 161.534 +            compare(key, key); // type (and possibly null) check
 161.535 +
 161.536 +            root = new Entry<>(key, value, null);
 161.537 +            size = 1;
 161.538 +            modCount++;
 161.539 +            return null;
 161.540 +        }
 161.541 +        int cmp;
 161.542 +        Entry<K,V> parent;
 161.543 +        // split comparator and comparable paths
 161.544 +        Comparator<? super K> cpr = comparator;
 161.545 +        if (cpr != null) {
 161.546 +            do {
 161.547 +                parent = t;
 161.548 +                cmp = cpr.compare(key, t.key);
 161.549 +                if (cmp < 0)
 161.550 +                    t = t.left;
 161.551 +                else if (cmp > 0)
 161.552 +                    t = t.right;
 161.553 +                else
 161.554 +                    return t.setValue(value);
 161.555 +            } while (t != null);
 161.556 +        }
 161.557 +        else {
 161.558 +            if (key == null)
 161.559 +                throw new NullPointerException();
 161.560 +            Comparable<? super K> k = (Comparable<? super K>) key;
 161.561 +            do {
 161.562 +                parent = t;
 161.563 +                cmp = k.compareTo(t.key);
 161.564 +                if (cmp < 0)
 161.565 +                    t = t.left;
 161.566 +                else if (cmp > 0)
 161.567 +                    t = t.right;
 161.568 +                else
 161.569 +                    return t.setValue(value);
 161.570 +            } while (t != null);
 161.571 +        }
 161.572 +        Entry<K,V> e = new Entry<>(key, value, parent);
 161.573 +        if (cmp < 0)
 161.574 +            parent.left = e;
 161.575 +        else
 161.576 +            parent.right = e;
 161.577 +        fixAfterInsertion(e);
 161.578 +        size++;
 161.579 +        modCount++;
 161.580 +        return null;
 161.581 +    }
 161.582 +
 161.583 +    /**
 161.584 +     * Removes the mapping for this key from this TreeMap if present.
 161.585 +     *
 161.586 +     * @param  key key for which mapping should be removed
 161.587 +     * @return the previous value associated with {@code key}, or
 161.588 +     *         {@code null} if there was no mapping for {@code key}.
 161.589 +     *         (A {@code null} return can also indicate that the map
 161.590 +     *         previously associated {@code null} with {@code key}.)
 161.591 +     * @throws ClassCastException if the specified key cannot be compared
 161.592 +     *         with the keys currently in the map
 161.593 +     * @throws NullPointerException if the specified key is null
 161.594 +     *         and this map uses natural ordering, or its comparator
 161.595 +     *         does not permit null keys
 161.596 +     */
 161.597 +    public V remove(Object key) {
 161.598 +        Entry<K,V> p = getEntry(key);
 161.599 +        if (p == null)
 161.600 +            return null;
 161.601 +
 161.602 +        V oldValue = p.value;
 161.603 +        deleteEntry(p);
 161.604 +        return oldValue;
 161.605 +    }
 161.606 +
 161.607 +    /**
 161.608 +     * Removes all of the mappings from this map.
 161.609 +     * The map will be empty after this call returns.
 161.610 +     */
 161.611 +    public void clear() {
 161.612 +        modCount++;
 161.613 +        size = 0;
 161.614 +        root = null;
 161.615 +    }
 161.616 +
 161.617 +    /**
 161.618 +     * Returns a shallow copy of this {@code TreeMap} instance. (The keys and
 161.619 +     * values themselves are not cloned.)
 161.620 +     *
 161.621 +     * @return a shallow copy of this map
 161.622 +     */
 161.623 +    public Object clone() {
 161.624 +        TreeMap<K,V> clone = null;
 161.625 +        try {
 161.626 +            clone = (TreeMap<K,V>) super.clone();
 161.627 +        } catch (CloneNotSupportedException e) {
 161.628 +            throw new InternalError();
 161.629 +        }
 161.630 +
 161.631 +        // Put clone into "virgin" state (except for comparator)
 161.632 +        clone.root = null;
 161.633 +        clone.size = 0;
 161.634 +        clone.modCount = 0;
 161.635 +        clone.entrySet = null;
 161.636 +        clone.navigableKeySet = null;
 161.637 +        clone.descendingMap = null;
 161.638 +
 161.639 +        // Initialize clone with our mappings
 161.640 +        try {
 161.641 +            clone.buildFromSorted(size, entrySet().iterator(), null, null);
 161.642 +        } catch (java.io.IOException cannotHappen) {
 161.643 +        } catch (ClassNotFoundException cannotHappen) {
 161.644 +        }
 161.645 +
 161.646 +        return clone;
 161.647 +    }
 161.648 +
 161.649 +    // NavigableMap API methods
 161.650 +
 161.651 +    /**
 161.652 +     * @since 1.6
 161.653 +     */
 161.654 +    public Map.Entry<K,V> firstEntry() {
 161.655 +        return exportEntry(getFirstEntry());
 161.656 +    }
 161.657 +
 161.658 +    /**
 161.659 +     * @since 1.6
 161.660 +     */
 161.661 +    public Map.Entry<K,V> lastEntry() {
 161.662 +        return exportEntry(getLastEntry());
 161.663 +    }
 161.664 +
 161.665 +    /**
 161.666 +     * @since 1.6
 161.667 +     */
 161.668 +    public Map.Entry<K,V> pollFirstEntry() {
 161.669 +        Entry<K,V> p = getFirstEntry();
 161.670 +        Map.Entry<K,V> result = exportEntry(p);
 161.671 +        if (p != null)
 161.672 +            deleteEntry(p);
 161.673 +        return result;
 161.674 +    }
 161.675 +
 161.676 +    /**
 161.677 +     * @since 1.6
 161.678 +     */
 161.679 +    public Map.Entry<K,V> pollLastEntry() {
 161.680 +        Entry<K,V> p = getLastEntry();
 161.681 +        Map.Entry<K,V> result = exportEntry(p);
 161.682 +        if (p != null)
 161.683 +            deleteEntry(p);
 161.684 +        return result;
 161.685 +    }
 161.686 +
 161.687 +    /**
 161.688 +     * @throws ClassCastException {@inheritDoc}
 161.689 +     * @throws NullPointerException if the specified key is null
 161.690 +     *         and this map uses natural ordering, or its comparator
 161.691 +     *         does not permit null keys
 161.692 +     * @since 1.6
 161.693 +     */
 161.694 +    public Map.Entry<K,V> lowerEntry(K key) {
 161.695 +        return exportEntry(getLowerEntry(key));
 161.696 +    }
 161.697 +
 161.698 +    /**
 161.699 +     * @throws ClassCastException {@inheritDoc}
 161.700 +     * @throws NullPointerException if the specified key is null
 161.701 +     *         and this map uses natural ordering, or its comparator
 161.702 +     *         does not permit null keys
 161.703 +     * @since 1.6
 161.704 +     */
 161.705 +    public K lowerKey(K key) {
 161.706 +        return keyOrNull(getLowerEntry(key));
 161.707 +    }
 161.708 +
 161.709 +    /**
 161.710 +     * @throws ClassCastException {@inheritDoc}
 161.711 +     * @throws NullPointerException if the specified key is null
 161.712 +     *         and this map uses natural ordering, or its comparator
 161.713 +     *         does not permit null keys
 161.714 +     * @since 1.6
 161.715 +     */
 161.716 +    public Map.Entry<K,V> floorEntry(K key) {
 161.717 +        return exportEntry(getFloorEntry(key));
 161.718 +    }
 161.719 +
 161.720 +    /**
 161.721 +     * @throws ClassCastException {@inheritDoc}
 161.722 +     * @throws NullPointerException if the specified key is null
 161.723 +     *         and this map uses natural ordering, or its comparator
 161.724 +     *         does not permit null keys
 161.725 +     * @since 1.6
 161.726 +     */
 161.727 +    public K floorKey(K key) {
 161.728 +        return keyOrNull(getFloorEntry(key));
 161.729 +    }
 161.730 +
 161.731 +    /**
 161.732 +     * @throws ClassCastException {@inheritDoc}
 161.733 +     * @throws NullPointerException if the specified key is null
 161.734 +     *         and this map uses natural ordering, or its comparator
 161.735 +     *         does not permit null keys
 161.736 +     * @since 1.6
 161.737 +     */
 161.738 +    public Map.Entry<K,V> ceilingEntry(K key) {
 161.739 +        return exportEntry(getCeilingEntry(key));
 161.740 +    }
 161.741 +
 161.742 +    /**
 161.743 +     * @throws ClassCastException {@inheritDoc}
 161.744 +     * @throws NullPointerException if the specified key is null
 161.745 +     *         and this map uses natural ordering, or its comparator
 161.746 +     *         does not permit null keys
 161.747 +     * @since 1.6
 161.748 +     */
 161.749 +    public K ceilingKey(K key) {
 161.750 +        return keyOrNull(getCeilingEntry(key));
 161.751 +    }
 161.752 +
 161.753 +    /**
 161.754 +     * @throws ClassCastException {@inheritDoc}
 161.755 +     * @throws NullPointerException if the specified key is null
 161.756 +     *         and this map uses natural ordering, or its comparator
 161.757 +     *         does not permit null keys
 161.758 +     * @since 1.6
 161.759 +     */
 161.760 +    public Map.Entry<K,V> higherEntry(K key) {
 161.761 +        return exportEntry(getHigherEntry(key));
 161.762 +    }
 161.763 +
 161.764 +    /**
 161.765 +     * @throws ClassCastException {@inheritDoc}
 161.766 +     * @throws NullPointerException if the specified key is null
 161.767 +     *         and this map uses natural ordering, or its comparator
 161.768 +     *         does not permit null keys
 161.769 +     * @since 1.6
 161.770 +     */
 161.771 +    public K higherKey(K key) {
 161.772 +        return keyOrNull(getHigherEntry(key));
 161.773 +    }
 161.774 +
 161.775 +    // Views
 161.776 +
 161.777 +    /**
 161.778 +     * Fields initialized to contain an instance of the entry set view
 161.779 +     * the first time this view is requested.  Views are stateless, so
 161.780 +     * there's no reason to create more than one.
 161.781 +     */
 161.782 +    private transient EntrySet entrySet = null;
 161.783 +    private transient KeySet<K> navigableKeySet = null;
 161.784 +    private transient NavigableMap<K,V> descendingMap = null;
 161.785 +
 161.786 +    /**
 161.787 +     * Returns a {@link Set} view of the keys contained in this map.
 161.788 +     * The set's iterator returns the keys in ascending order.
 161.789 +     * The set is backed by the map, so changes to the map are
 161.790 +     * reflected in the set, and vice-versa.  If the map is modified
 161.791 +     * while an iteration over the set is in progress (except through
 161.792 +     * the iterator's own {@code remove} operation), the results of
 161.793 +     * the iteration are undefined.  The set supports element removal,
 161.794 +     * which removes the corresponding mapping from the map, via the
 161.795 +     * {@code Iterator.remove}, {@code Set.remove},
 161.796 +     * {@code removeAll}, {@code retainAll}, and {@code clear}
 161.797 +     * operations.  It does not support the {@code add} or {@code addAll}
 161.798 +     * operations.
 161.799 +     */
 161.800 +    public Set<K> keySet() {
 161.801 +        return navigableKeySet();
 161.802 +    }
 161.803 +
 161.804 +    /**
 161.805 +     * @since 1.6
 161.806 +     */
 161.807 +    public NavigableSet<K> navigableKeySet() {
 161.808 +        KeySet<K> nks = navigableKeySet;
 161.809 +        return (nks != null) ? nks : (navigableKeySet = new KeySet(this));
 161.810 +    }
 161.811 +
 161.812 +    /**
 161.813 +     * @since 1.6
 161.814 +     */
 161.815 +    public NavigableSet<K> descendingKeySet() {
 161.816 +        return descendingMap().navigableKeySet();
 161.817 +    }
 161.818 +
 161.819 +    /**
 161.820 +     * Returns a {@link Collection} view of the values contained in this map.
 161.821 +     * The collection's iterator returns the values in ascending order
 161.822 +     * of the corresponding keys.
 161.823 +     * The collection is backed by the map, so changes to the map are
 161.824 +     * reflected in the collection, and vice-versa.  If the map is
 161.825 +     * modified while an iteration over the collection is in progress
 161.826 +     * (except through the iterator's own {@code remove} operation),
 161.827 +     * the results of the iteration are undefined.  The collection
 161.828 +     * supports element removal, which removes the corresponding
 161.829 +     * mapping from the map, via the {@code Iterator.remove},
 161.830 +     * {@code Collection.remove}, {@code removeAll},
 161.831 +     * {@code retainAll} and {@code clear} operations.  It does not
 161.832 +     * support the {@code add} or {@code addAll} operations.
 161.833 +     */
 161.834 +    public Collection<V> values() {
 161.835 +        Collection<V> vs = values;
 161.836 +        return (vs != null) ? vs : (values = new Values());
 161.837 +    }
 161.838 +
 161.839 +    /**
 161.840 +     * Returns a {@link Set} view of the mappings contained in this map.
 161.841 +     * The set's iterator returns the entries in ascending key order.
 161.842 +     * The set is backed by the map, so changes to the map are
 161.843 +     * reflected in the set, and vice-versa.  If the map is modified
 161.844 +     * while an iteration over the set is in progress (except through
 161.845 +     * the iterator's own {@code remove} operation, or through the
 161.846 +     * {@code setValue} operation on a map entry returned by the
 161.847 +     * iterator) the results of the iteration are undefined.  The set
 161.848 +     * supports element removal, which removes the corresponding
 161.849 +     * mapping from the map, via the {@code Iterator.remove},
 161.850 +     * {@code Set.remove}, {@code removeAll}, {@code retainAll} and
 161.851 +     * {@code clear} operations.  It does not support the
 161.852 +     * {@code add} or {@code addAll} operations.
 161.853 +     */
 161.854 +    public Set<Map.Entry<K,V>> entrySet() {
 161.855 +        EntrySet es = entrySet;
 161.856 +        return (es != null) ? es : (entrySet = new EntrySet());
 161.857 +    }
 161.858 +
 161.859 +    /**
 161.860 +     * @since 1.6
 161.861 +     */
 161.862 +    public NavigableMap<K, V> descendingMap() {
 161.863 +        NavigableMap<K, V> km = descendingMap;
 161.864 +        return (km != null) ? km :
 161.865 +            (descendingMap = new DescendingSubMap(this,
 161.866 +                                                  true, null, true,
 161.867 +                                                  true, null, true));
 161.868 +    }
 161.869 +
 161.870 +    /**
 161.871 +     * @throws ClassCastException       {@inheritDoc}
 161.872 +     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
 161.873 +     *         null and this map uses natural ordering, or its comparator
 161.874 +     *         does not permit null keys
 161.875 +     * @throws IllegalArgumentException {@inheritDoc}
 161.876 +     * @since 1.6
 161.877 +     */
 161.878 +    public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
 161.879 +                                    K toKey,   boolean toInclusive) {
 161.880 +        return new AscendingSubMap(this,
 161.881 +                                   false, fromKey, fromInclusive,
 161.882 +                                   false, toKey,   toInclusive);
 161.883 +    }
 161.884 +
 161.885 +    /**
 161.886 +     * @throws ClassCastException       {@inheritDoc}
 161.887 +     * @throws NullPointerException if {@code toKey} is null
 161.888 +     *         and this map uses natural ordering, or its comparator
 161.889 +     *         does not permit null keys
 161.890 +     * @throws IllegalArgumentException {@inheritDoc}
 161.891 +     * @since 1.6
 161.892 +     */
 161.893 +    public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
 161.894 +        return new AscendingSubMap(this,
 161.895 +                                   true,  null,  true,
 161.896 +                                   false, toKey, inclusive);
 161.897 +    }
 161.898 +
 161.899 +    /**
 161.900 +     * @throws ClassCastException       {@inheritDoc}
 161.901 +     * @throws NullPointerException if {@code fromKey} is null
 161.902 +     *         and this map uses natural ordering, or its comparator
 161.903 +     *         does not permit null keys
 161.904 +     * @throws IllegalArgumentException {@inheritDoc}
 161.905 +     * @since 1.6
 161.906 +     */
 161.907 +    public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
 161.908 +        return new AscendingSubMap(this,
 161.909 +                                   false, fromKey, inclusive,
 161.910 +                                   true,  null,    true);
 161.911 +    }
 161.912 +
 161.913 +    /**
 161.914 +     * @throws ClassCastException       {@inheritDoc}
 161.915 +     * @throws NullPointerException if {@code fromKey} or {@code toKey} is
 161.916 +     *         null and this map uses natural ordering, or its comparator
 161.917 +     *         does not permit null keys
 161.918 +     * @throws IllegalArgumentException {@inheritDoc}
 161.919 +     */
 161.920 +    public SortedMap<K,V> subMap(K fromKey, K toKey) {
 161.921 +        return subMap(fromKey, true, toKey, false);
 161.922 +    }
 161.923 +
 161.924 +    /**
 161.925 +     * @throws ClassCastException       {@inheritDoc}
 161.926 +     * @throws NullPointerException if {@code toKey} is null
 161.927 +     *         and this map uses natural ordering, or its comparator
 161.928 +     *         does not permit null keys
 161.929 +     * @throws IllegalArgumentException {@inheritDoc}
 161.930 +     */
 161.931 +    public SortedMap<K,V> headMap(K toKey) {
 161.932 +        return headMap(toKey, false);
 161.933 +    }
 161.934 +
 161.935 +    /**
 161.936 +     * @throws ClassCastException       {@inheritDoc}
 161.937 +     * @throws NullPointerException if {@code fromKey} is null
 161.938 +     *         and this map uses natural ordering, or its comparator
 161.939 +     *         does not permit null keys
 161.940 +     * @throws IllegalArgumentException {@inheritDoc}
 161.941 +     */
 161.942 +    public SortedMap<K,V> tailMap(K fromKey) {
 161.943 +        return tailMap(fromKey, true);
 161.944 +    }
 161.945 +
 161.946 +    // View class support
 161.947 +
 161.948 +    class Values extends AbstractCollection<V> {
 161.949 +        public Iterator<V> iterator() {
 161.950 +            return new ValueIterator(getFirstEntry());
 161.951 +        }
 161.952 +
 161.953 +        public int size() {
 161.954 +            return TreeMap.this.size();
 161.955 +        }
 161.956 +
 161.957 +        public boolean contains(Object o) {
 161.958 +            return TreeMap.this.containsValue(o);
 161.959 +        }
 161.960 +
 161.961 +        public boolean remove(Object o) {
 161.962 +            for (Entry<K,V> e = getFirstEntry(); e != null; e = successor(e)) {
 161.963 +                if (valEquals(e.getValue(), o)) {
 161.964 +                    deleteEntry(e);
 161.965 +                    return true;
 161.966 +                }
 161.967 +            }
 161.968 +            return false;
 161.969 +        }
 161.970 +
 161.971 +        public void clear() {
 161.972 +            TreeMap.this.clear();
 161.973 +        }
 161.974 +    }
 161.975 +
 161.976 +    class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 161.977 +        public Iterator<Map.Entry<K,V>> iterator() {
 161.978 +            return new EntryIterator(getFirstEntry());
 161.979 +        }
 161.980 +
 161.981 +        public boolean contains(Object o) {
 161.982 +            if (!(o instanceof Map.Entry))
 161.983 +                return false;
 161.984 +            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 161.985 +            V value = entry.getValue();
 161.986 +            Entry<K,V> p = getEntry(entry.getKey());
 161.987 +            return p != null && valEquals(p.getValue(), value);
 161.988 +        }
 161.989 +
 161.990 +        public boolean remove(Object o) {
 161.991 +            if (!(o instanceof Map.Entry))
 161.992 +                return false;
 161.993 +            Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
 161.994 +            V value = entry.getValue();
 161.995 +            Entry<K,V> p = getEntry(entry.getKey());
 161.996 +            if (p != null && valEquals(p.getValue(), value)) {
 161.997 +                deleteEntry(p);
 161.998 +                return true;
 161.999 +            }
161.1000 +            return false;
161.1001 +        }
161.1002 +
161.1003 +        public int size() {
161.1004 +            return TreeMap.this.size();
161.1005 +        }
161.1006 +
161.1007 +        public void clear() {
161.1008 +            TreeMap.this.clear();
161.1009 +        }
161.1010 +    }
161.1011 +
161.1012 +    /*
161.1013 +     * Unlike Values and EntrySet, the KeySet class is static,
161.1014 +     * delegating to a NavigableMap to allow use by SubMaps, which
161.1015 +     * outweighs the ugliness of needing type-tests for the following
161.1016 +     * Iterator methods that are defined appropriately in main versus
161.1017 +     * submap classes.
161.1018 +     */
161.1019 +
161.1020 +    Iterator<K> keyIterator() {
161.1021 +        return new KeyIterator(getFirstEntry());
161.1022 +    }
161.1023 +
161.1024 +    Iterator<K> descendingKeyIterator() {
161.1025 +        return new DescendingKeyIterator(getLastEntry());
161.1026 +    }
161.1027 +
161.1028 +    static final class KeySet<E> extends AbstractSet<E> implements NavigableSet<E> {
161.1029 +        private final NavigableMap<E, Object> m;
161.1030 +        KeySet(NavigableMap<E,Object> map) { m = map; }
161.1031 +
161.1032 +        public Iterator<E> iterator() {
161.1033 +            if (m instanceof TreeMap)
161.1034 +                return ((TreeMap<E,Object>)m).keyIterator();
161.1035 +            else
161.1036 +                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).keyIterator());
161.1037 +        }
161.1038 +
161.1039 +        public Iterator<E> descendingIterator() {
161.1040 +            if (m instanceof TreeMap)
161.1041 +                return ((TreeMap<E,Object>)m).descendingKeyIterator();
161.1042 +            else
161.1043 +                return (Iterator<E>)(((TreeMap.NavigableSubMap)m).descendingKeyIterator());
161.1044 +        }
161.1045 +
161.1046 +        public int size() { return m.size(); }
161.1047 +        public boolean isEmpty() { return m.isEmpty(); }
161.1048 +        public boolean contains(Object o) { return m.containsKey(o); }
161.1049 +        public void clear() { m.clear(); }
161.1050 +        public E lower(E e) { return m.lowerKey(e); }
161.1051 +        public E floor(E e) { return m.floorKey(e); }
161.1052 +        public E ceiling(E e) { return m.ceilingKey(e); }
161.1053 +        public E higher(E e) { return m.higherKey(e); }
161.1054 +        public E first() { return m.firstKey(); }
161.1055 +        public E last() { return m.lastKey(); }
161.1056 +        public Comparator<? super E> comparator() { return m.comparator(); }
161.1057 +        public E pollFirst() {
161.1058 +            Map.Entry<E,Object> e = m.pollFirstEntry();
161.1059 +            return (e == null) ? null : e.getKey();
161.1060 +        }
161.1061 +        public E pollLast() {
161.1062 +            Map.Entry<E,Object> e = m.pollLastEntry();
161.1063 +            return (e == null) ? null : e.getKey();
161.1064 +        }
161.1065 +        public boolean remove(Object o) {
161.1066 +            int oldSize = size();
161.1067 +            m.remove(o);
161.1068 +            return size() != oldSize;
161.1069 +        }
161.1070 +        public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
161.1071 +                                      E toElement,   boolean toInclusive) {
161.1072 +            return new KeySet<>(m.subMap(fromElement, fromInclusive,
161.1073 +                                          toElement,   toInclusive));
161.1074 +        }
161.1075 +        public NavigableSet<E> headSet(E toElement, boolean inclusive) {
161.1076 +            return new KeySet<>(m.headMap(toElement, inclusive));
161.1077 +        }
161.1078 +        public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
161.1079 +            return new KeySet<>(m.tailMap(fromElement, inclusive));
161.1080 +        }
161.1081 +        public SortedSet<E> subSet(E fromElement, E toElement) {
161.1082 +            return subSet(fromElement, true, toElement, false);
161.1083 +        }
161.1084 +        public SortedSet<E> headSet(E toElement) {
161.1085 +            return headSet(toElement, false);
161.1086 +        }
161.1087 +        public SortedSet<E> tailSet(E fromElement) {
161.1088 +            return tailSet(fromElement, true);
161.1089 +        }
161.1090 +        public NavigableSet<E> descendingSet() {
161.1091 +            return new KeySet(m.descendingMap());
161.1092 +        }
161.1093 +    }
161.1094 +
161.1095 +    /**
161.1096 +     * Base class for TreeMap Iterators
161.1097 +     */
161.1098 +    abstract class PrivateEntryIterator<T> implements Iterator<T> {
161.1099 +        Entry<K,V> next;
161.1100 +        Entry<K,V> lastReturned;
161.1101 +        int expectedModCount;
161.1102 +
161.1103 +        PrivateEntryIterator(Entry<K,V> first) {
161.1104 +            expectedModCount = modCount;
161.1105 +            lastReturned = null;
161.1106 +            next = first;
161.1107 +        }
161.1108 +
161.1109 +        public final boolean hasNext() {
161.1110 +            return next != null;
161.1111 +        }
161.1112 +
161.1113 +        final Entry<K,V> nextEntry() {
161.1114 +            Entry<K,V> e = next;
161.1115 +            if (e == null)
161.1116 +                throw new NoSuchElementException();
161.1117 +            if (modCount != expectedModCount)
161.1118 +                throw new ConcurrentModificationException();
161.1119 +            next = successor(e);
161.1120 +            lastReturned = e;
161.1121 +            return e;
161.1122 +        }
161.1123 +
161.1124 +        final Entry<K,V> prevEntry() {
161.1125 +            Entry<K,V> e = next;
161.1126 +            if (e == null)
161.1127 +                throw new NoSuchElementException();
161.1128 +            if (modCount != expectedModCount)
161.1129 +                throw new ConcurrentModificationException();
161.1130 +            next = predecessor(e);
161.1131 +            lastReturned = e;
161.1132 +            return e;
161.1133 +        }
161.1134 +
161.1135 +        public void remove() {
161.1136 +            if (lastReturned == null)
161.1137 +                throw new IllegalStateException();
161.1138 +            if (modCount != expectedModCount)
161.1139 +                throw new ConcurrentModificationException();
161.1140 +            // deleted entries are replaced by their successors
161.1141 +            if (lastReturned.left != null && lastReturned.right != null)
161.1142 +                next = lastReturned;
161.1143 +            deleteEntry(lastReturned);
161.1144 +            expectedModCount = modCount;
161.1145 +            lastReturned = null;
161.1146 +        }
161.1147 +    }
161.1148 +
161.1149 +    final class EntryIterator extends PrivateEntryIterator<Map.Entry<K,V>> {
161.1150 +        EntryIterator(Entry<K,V> first) {
161.1151 +            super(first);
161.1152 +        }
161.1153 +        public Map.Entry<K,V> next() {
161.1154 +            return nextEntry();
161.1155 +        }
161.1156 +    }
161.1157 +
161.1158 +    final class ValueIterator extends PrivateEntryIterator<V> {
161.1159 +        ValueIterator(Entry<K,V> first) {
161.1160 +            super(first);
161.1161 +        }
161.1162 +        public V next() {
161.1163 +            return nextEntry().value;
161.1164 +        }
161.1165 +    }
161.1166 +
161.1167 +    final class KeyIterator extends PrivateEntryIterator<K> {
161.1168 +        KeyIterator(Entry<K,V> first) {
161.1169 +            super(first);
161.1170 +        }
161.1171 +        public K next() {
161.1172 +            return nextEntry().key;
161.1173 +        }
161.1174 +    }
161.1175 +
161.1176 +    final class DescendingKeyIterator extends PrivateEntryIterator<K> {
161.1177 +        DescendingKeyIterator(Entry<K,V> first) {
161.1178 +            super(first);
161.1179 +        }
161.1180 +        public K next() {
161.1181 +            return prevEntry().key;
161.1182 +        }
161.1183 +    }
161.1184 +
161.1185 +    // Little utilities
161.1186 +
161.1187 +    /**
161.1188 +     * Compares two keys using the correct comparison method for this TreeMap.
161.1189 +     */
161.1190 +    final int compare(Object k1, Object k2) {
161.1191 +        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
161.1192 +            : comparator.compare((K)k1, (K)k2);
161.1193 +    }
161.1194 +
161.1195 +    /**
161.1196 +     * Test two values for equality.  Differs from o1.equals(o2) only in
161.1197 +     * that it copes with {@code null} o1 properly.
161.1198 +     */
161.1199 +    static final boolean valEquals(Object o1, Object o2) {
161.1200 +        return (o1==null ? o2==null : o1.equals(o2));
161.1201 +    }
161.1202 +
161.1203 +    /**
161.1204 +     * Return SimpleImmutableEntry for entry, or null if null
161.1205 +     */
161.1206 +    static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
161.1207 +        return (e == null) ? null :
161.1208 +            new AbstractMap.SimpleImmutableEntry<>(e);
161.1209 +    }
161.1210 +
161.1211 +    /**
161.1212 +     * Return key for entry, or null if null
161.1213 +     */
161.1214 +    static <K,V> K keyOrNull(TreeMap.Entry<K,V> e) {
161.1215 +        return (e == null) ? null : e.key;
161.1216 +    }
161.1217 +
161.1218 +    /**
161.1219 +     * Returns the key corresponding to the specified Entry.
161.1220 +     * @throws NoSuchElementException if the Entry is null
161.1221 +     */
161.1222 +    static <K> K key(Entry<K,?> e) {
161.1223 +        if (e==null)
161.1224 +            throw new NoSuchElementException();
161.1225 +        return e.key;
161.1226 +    }
161.1227 +
161.1228 +
161.1229 +    // SubMaps
161.1230 +
161.1231 +    /**
161.1232 +     * Dummy value serving as unmatchable fence key for unbounded
161.1233 +     * SubMapIterators
161.1234 +     */
161.1235 +    private static final Object UNBOUNDED = new Object();
161.1236 +
161.1237 +    /**
161.1238 +     * @serial include
161.1239 +     */
161.1240 +    abstract static class NavigableSubMap<K,V> extends AbstractMap<K,V>
161.1241 +        implements NavigableMap<K,V>, java.io.Serializable {
161.1242 +        /**
161.1243 +         * The backing map.
161.1244 +         */
161.1245 +        final TreeMap<K,V> m;
161.1246 +
161.1247 +        /**
161.1248 +         * Endpoints are represented as triples (fromStart, lo,
161.1249 +         * loInclusive) and (toEnd, hi, hiInclusive). If fromStart is
161.1250 +         * true, then the low (absolute) bound is the start of the
161.1251 +         * backing map, and the other values are ignored. Otherwise,
161.1252 +         * if loInclusive is true, lo is the inclusive bound, else lo
161.1253 +         * is the exclusive bound. Similarly for the upper bound.
161.1254 +         */
161.1255 +        final K lo, hi;
161.1256 +        final boolean fromStart, toEnd;
161.1257 +        final boolean loInclusive, hiInclusive;
161.1258 +
161.1259 +        NavigableSubMap(TreeMap<K,V> m,
161.1260 +                        boolean fromStart, K lo, boolean loInclusive,
161.1261 +                        boolean toEnd,     K hi, boolean hiInclusive) {
161.1262 +            if (!fromStart && !toEnd) {
161.1263 +                if (m.compare(lo, hi) > 0)
161.1264 +                    throw new IllegalArgumentException("fromKey > toKey");
161.1265 +            } else {
161.1266 +                if (!fromStart) // type check
161.1267 +                    m.compare(lo, lo);
161.1268 +                if (!toEnd)
161.1269 +                    m.compare(hi, hi);
161.1270 +            }
161.1271 +
161.1272 +            this.m = m;
161.1273 +            this.fromStart = fromStart;
161.1274 +            this.lo = lo;
161.1275 +            this.loInclusive = loInclusive;
161.1276 +            this.toEnd = toEnd;
161.1277 +            this.hi = hi;
161.1278 +            this.hiInclusive = hiInclusive;
161.1279 +        }
161.1280 +
161.1281 +        // internal utilities
161.1282 +
161.1283 +        final boolean tooLow(Object key) {
161.1284 +            if (!fromStart) {
161.1285 +                int c = m.compare(key, lo);
161.1286 +                if (c < 0 || (c == 0 && !loInclusive))
161.1287 +                    return true;
161.1288 +            }
161.1289 +            return false;
161.1290 +        }
161.1291 +
161.1292 +        final boolean tooHigh(Object key) {
161.1293 +            if (!toEnd) {
161.1294 +                int c = m.compare(key, hi);
161.1295 +                if (c > 0 || (c == 0 && !hiInclusive))
161.1296 +                    return true;
161.1297 +            }
161.1298 +            return false;
161.1299 +        }
161.1300 +
161.1301 +        final boolean inRange(Object key) {
161.1302 +            return !tooLow(key) && !tooHigh(key);
161.1303 +        }
161.1304 +
161.1305 +        final boolean inClosedRange(Object key) {
161.1306 +            return (fromStart || m.compare(key, lo) >= 0)
161.1307 +                && (toEnd || m.compare(hi, key) >= 0);
161.1308 +        }
161.1309 +
161.1310 +        final boolean inRange(Object key, boolean inclusive) {
161.1311 +            return inclusive ? inRange(key) : inClosedRange(key);
161.1312 +        }
161.1313 +
161.1314 +        /*
161.1315 +         * Absolute versions of relation operations.
161.1316 +         * Subclasses map to these using like-named "sub"
161.1317 +         * versions that invert senses for descending maps
161.1318 +         */
161.1319 +
161.1320 +        final TreeMap.Entry<K,V> absLowest() {
161.1321 +            TreeMap.Entry<K,V> e =
161.1322 +                (fromStart ?  m.getFirstEntry() :
161.1323 +                 (loInclusive ? m.getCeilingEntry(lo) :
161.1324 +                                m.getHigherEntry(lo)));
161.1325 +            return (e == null || tooHigh(e.key)) ? null : e;
161.1326 +        }
161.1327 +
161.1328 +        final TreeMap.Entry<K,V> absHighest() {
161.1329 +            TreeMap.Entry<K,V> e =
161.1330 +                (toEnd ?  m.getLastEntry() :
161.1331 +                 (hiInclusive ?  m.getFloorEntry(hi) :
161.1332 +                                 m.getLowerEntry(hi)));
161.1333 +            return (e == null || tooLow(e.key)) ? null : e;
161.1334 +        }
161.1335 +
161.1336 +        final TreeMap.Entry<K,V> absCeiling(K key) {
161.1337 +            if (tooLow(key))
161.1338 +                return absLowest();
161.1339 +            TreeMap.Entry<K,V> e = m.getCeilingEntry(key);
161.1340 +            return (e == null || tooHigh(e.key)) ? null : e;
161.1341 +        }
161.1342 +
161.1343 +        final TreeMap.Entry<K,V> absHigher(K key) {
161.1344 +            if (tooLow(key))
161.1345 +                return absLowest();
161.1346 +            TreeMap.Entry<K,V> e = m.getHigherEntry(key);
161.1347 +            return (e == null || tooHigh(e.key)) ? null : e;
161.1348 +        }
161.1349 +
161.1350 +        final TreeMap.Entry<K,V> absFloor(K key) {
161.1351 +            if (tooHigh(key))
161.1352 +                return absHighest();
161.1353 +            TreeMap.Entry<K,V> e = m.getFloorEntry(key);
161.1354 +            return (e == null || tooLow(e.key)) ? null : e;
161.1355 +        }
161.1356 +
161.1357 +        final TreeMap.Entry<K,V> absLower(K key) {
161.1358 +            if (tooHigh(key))
161.1359 +                return absHighest();
161.1360 +            TreeMap.Entry<K,V> e = m.getLowerEntry(key);
161.1361 +            return (e == null || tooLow(e.key)) ? null : e;
161.1362 +        }
161.1363 +
161.1364 +        /** Returns the absolute high fence for ascending traversal */
161.1365 +        final TreeMap.Entry<K,V> absHighFence() {
161.1366 +            return (toEnd ? null : (hiInclusive ?
161.1367 +                                    m.getHigherEntry(hi) :
161.1368 +                                    m.getCeilingEntry(hi)));
161.1369 +        }
161.1370 +
161.1371 +        /** Return the absolute low fence for descending traversal  */
161.1372 +        final TreeMap.Entry<K,V> absLowFence() {
161.1373 +            return (fromStart ? null : (loInclusive ?
161.1374 +                                        m.getLowerEntry(lo) :
161.1375 +                                        m.getFloorEntry(lo)));
161.1376 +        }
161.1377 +
161.1378 +        // Abstract methods defined in ascending vs descending classes
161.1379 +        // These relay to the appropriate absolute versions
161.1380 +
161.1381 +        abstract TreeMap.Entry<K,V> subLowest();
161.1382 +        abstract TreeMap.Entry<K,V> subHighest();
161.1383 +        abstract TreeMap.Entry<K,V> subCeiling(K key);
161.1384 +        abstract TreeMap.Entry<K,V> subHigher(K key);
161.1385 +        abstract TreeMap.Entry<K,V> subFloor(K key);
161.1386 +        abstract TreeMap.Entry<K,V> subLower(K key);
161.1387 +
161.1388 +        /** Returns ascending iterator from the perspective of this submap */
161.1389 +        abstract Iterator<K> keyIterator();
161.1390 +
161.1391 +        /** Returns descending iterator from the perspective of this submap */
161.1392 +        abstract Iterator<K> descendingKeyIterator();
161.1393 +
161.1394 +        // public methods
161.1395 +
161.1396 +        public boolean isEmpty() {
161.1397 +            return (fromStart && toEnd) ? m.isEmpty() : entrySet().isEmpty();
161.1398 +        }
161.1399 +
161.1400 +        public int size() {
161.1401 +            return (fromStart && toEnd) ? m.size() : entrySet().size();
161.1402 +        }
161.1403 +
161.1404 +        public final boolean containsKey(Object key) {
161.1405 +            return inRange(key) && m.containsKey(key);
161.1406 +        }
161.1407 +
161.1408 +        public final V put(K key, V value) {
161.1409 +            if (!inRange(key))
161.1410 +                throw new IllegalArgumentException("key out of range");
161.1411 +            return m.put(key, value);
161.1412 +        }
161.1413 +
161.1414 +        public final V get(Object key) {
161.1415 +            return !inRange(key) ? null :  m.get(key);
161.1416 +        }
161.1417 +
161.1418 +        public final V remove(Object key) {
161.1419 +            return !inRange(key) ? null : m.remove(key);
161.1420 +        }
161.1421 +
161.1422 +        public final Map.Entry<K,V> ceilingEntry(K key) {
161.1423 +            return exportEntry(subCeiling(key));
161.1424 +        }
161.1425 +
161.1426 +        public final K ceilingKey(K key) {
161.1427 +            return keyOrNull(subCeiling(key));
161.1428 +        }
161.1429 +
161.1430 +        public final Map.Entry<K,V> higherEntry(K key) {
161.1431 +            return exportEntry(subHigher(key));
161.1432 +        }
161.1433 +
161.1434 +        public final K higherKey(K key) {
161.1435 +            return keyOrNull(subHigher(key));
161.1436 +        }
161.1437 +
161.1438 +        public final Map.Entry<K,V> floorEntry(K key) {
161.1439 +            return exportEntry(subFloor(key));
161.1440 +        }
161.1441 +
161.1442 +        public final K floorKey(K key) {
161.1443 +            return keyOrNull(subFloor(key));
161.1444 +        }
161.1445 +
161.1446 +        public final Map.Entry<K,V> lowerEntry(K key) {
161.1447 +            return exportEntry(subLower(key));
161.1448 +        }
161.1449 +
161.1450 +        public final K lowerKey(K key) {
161.1451 +            return keyOrNull(subLower(key));
161.1452 +        }
161.1453 +
161.1454 +        public final K firstKey() {
161.1455 +            return key(subLowest());
161.1456 +        }
161.1457 +
161.1458 +        public final K lastKey() {
161.1459 +            return key(subHighest());
161.1460 +        }
161.1461 +
161.1462 +        public final Map.Entry<K,V> firstEntry() {
161.1463 +            return exportEntry(subLowest());
161.1464 +        }
161.1465 +
161.1466 +        public final Map.Entry<K,V> lastEntry() {
161.1467 +            return exportEntry(subHighest());
161.1468 +        }
161.1469 +
161.1470 +        public final Map.Entry<K,V> pollFirstEntry() {
161.1471 +            TreeMap.Entry<K,V> e = subLowest();
161.1472 +            Map.Entry<K,V> result = exportEntry(e);
161.1473 +            if (e != null)
161.1474 +                m.deleteEntry(e);
161.1475 +            return result;
161.1476 +        }
161.1477 +
161.1478 +        public final Map.Entry<K,V> pollLastEntry() {
161.1479 +            TreeMap.Entry<K,V> e = subHighest();
161.1480 +            Map.Entry<K,V> result = exportEntry(e);
161.1481 +            if (e != null)
161.1482 +                m.deleteEntry(e);
161.1483 +            return result;
161.1484 +        }
161.1485 +
161.1486 +        // Views
161.1487 +        transient NavigableMap<K,V> descendingMapView = null;
161.1488 +        transient EntrySetView entrySetView = null;
161.1489 +        transient KeySet<K> navigableKeySetView = null;
161.1490 +
161.1491 +        public final NavigableSet<K> navigableKeySet() {
161.1492 +            KeySet<K> nksv = navigableKeySetView;
161.1493 +            return (nksv != null) ? nksv :
161.1494 +                (navigableKeySetView = new TreeMap.KeySet(this));
161.1495 +        }
161.1496 +
161.1497 +        public final Set<K> keySet() {
161.1498 +            return navigableKeySet();
161.1499 +        }
161.1500 +
161.1501 +        public NavigableSet<K> descendingKeySet() {
161.1502 +            return descendingMap().navigableKeySet();
161.1503 +        }
161.1504 +
161.1505 +        public final SortedMap<K,V> subMap(K fromKey, K toKey) {
161.1506 +            return subMap(fromKey, true, toKey, false);
161.1507 +        }
161.1508 +
161.1509 +        public final SortedMap<K,V> headMap(K toKey) {
161.1510 +            return headMap(toKey, false);
161.1511 +        }
161.1512 +
161.1513 +        public final SortedMap<K,V> tailMap(K fromKey) {
161.1514 +            return tailMap(fromKey, true);
161.1515 +        }
161.1516 +
161.1517 +        // View classes
161.1518 +
161.1519 +        abstract class EntrySetView extends AbstractSet<Map.Entry<K,V>> {
161.1520 +            private transient int size = -1, sizeModCount;
161.1521 +
161.1522 +            public int size() {
161.1523 +                if (fromStart && toEnd)
161.1524 +                    return m.size();
161.1525 +                if (size == -1 || sizeModCount != m.modCount) {
161.1526 +                    sizeModCount = m.modCount;
161.1527 +                    size = 0;
161.1528 +                    Iterator i = iterator();
161.1529 +                    while (i.hasNext()) {
161.1530 +                        size++;
161.1531 +                        i.next();
161.1532 +                    }
161.1533 +                }
161.1534 +                return size;
161.1535 +            }
161.1536 +
161.1537 +            public boolean isEmpty() {
161.1538 +                TreeMap.Entry<K,V> n = absLowest();
161.1539 +                return n == null || tooHigh(n.key);
161.1540 +            }
161.1541 +
161.1542 +            public boolean contains(Object o) {
161.1543 +                if (!(o instanceof Map.Entry))
161.1544 +                    return false;
161.1545 +                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
161.1546 +                K key = entry.getKey();
161.1547 +                if (!inRange(key))
161.1548 +                    return false;
161.1549 +                TreeMap.Entry node = m.getEntry(key);
161.1550 +                return node != null &&
161.1551 +                    valEquals(node.getValue(), entry.getValue());
161.1552 +            }
161.1553 +
161.1554 +            public boolean remove(Object o) {
161.1555 +                if (!(o instanceof Map.Entry))
161.1556 +                    return false;
161.1557 +                Map.Entry<K,V> entry = (Map.Entry<K,V>) o;
161.1558 +                K key = entry.getKey();
161.1559 +                if (!inRange(key))
161.1560 +                    return false;
161.1561 +                TreeMap.Entry<K,V> node = m.getEntry(key);
161.1562 +                if (node!=null && valEquals(node.getValue(),
161.1563 +                                            entry.getValue())) {
161.1564 +                    m.deleteEntry(node);
161.1565 +                    return true;
161.1566 +                }
161.1567 +                return false;
161.1568 +            }
161.1569 +        }
161.1570 +
161.1571 +        /**
161.1572 +         * Iterators for SubMaps
161.1573 +         */
161.1574 +        abstract class SubMapIterator<T> implements Iterator<T> {
161.1575 +            TreeMap.Entry<K,V> lastReturned;
161.1576 +            TreeMap.Entry<K,V> next;
161.1577 +            final Object fenceKey;
161.1578 +            int expectedModCount;
161.1579 +
161.1580 +            SubMapIterator(TreeMap.Entry<K,V> first,
161.1581 +                           TreeMap.Entry<K,V> fence) {
161.1582 +                expectedModCount = m.modCount;
161.1583 +                lastReturned = null;
161.1584 +                next = first;
161.1585 +                fenceKey = fence == null ? UNBOUNDED : fence.key;
161.1586 +            }
161.1587 +
161.1588 +            public final boolean hasNext() {
161.1589 +                return next != null && next.key != fenceKey;
161.1590 +            }
161.1591 +
161.1592 +            final TreeMap.Entry<K,V> nextEntry() {
161.1593 +                TreeMap.Entry<K,V> e = next;
161.1594 +                if (e == null || e.key == fenceKey)
161.1595 +                    throw new NoSuchElementException();
161.1596 +                if (m.modCount != expectedModCount)
161.1597 +                    throw new ConcurrentModificationException();
161.1598 +                next = successor(e);
161.1599 +                lastReturned = e;
161.1600 +                return e;
161.1601 +            }
161.1602 +
161.1603 +            final TreeMap.Entry<K,V> prevEntry() {
161.1604 +                TreeMap.Entry<K,V> e = next;
161.1605 +                if (e == null || e.key == fenceKey)
161.1606 +                    throw new NoSuchElementException();
161.1607 +                if (m.modCount != expectedModCount)
161.1608 +                    throw new ConcurrentModificationException();
161.1609 +                next = predecessor(e);
161.1610 +                lastReturned = e;
161.1611 +                return e;
161.1612 +            }
161.1613 +
161.1614 +            final void removeAscending() {
161.1615 +                if (lastReturned == null)
161.1616 +                    throw new IllegalStateException();
161.1617 +                if (m.modCount != expectedModCount)
161.1618 +                    throw new ConcurrentModificationException();
161.1619 +                // deleted entries are replaced by their successors
161.1620 +                if (lastReturned.left != null && lastReturned.right != null)
161.1621 +                    next = lastReturned;
161.1622 +                m.deleteEntry(lastReturned);
161.1623 +                lastReturned = null;
161.1624 +                expectedModCount = m.modCount;
161.1625 +            }
161.1626 +
161.1627 +            final void removeDescending() {
161.1628 +                if (lastReturned == null)
161.1629 +                    throw new IllegalStateException();
161.1630 +                if (m.modCount != expectedModCount)
161.1631 +                    throw new ConcurrentModificationException();
161.1632 +                m.deleteEntry(lastReturned);
161.1633 +                lastReturned = null;
161.1634 +                expectedModCount = m.modCount;
161.1635 +            }
161.1636 +
161.1637 +        }
161.1638 +
161.1639 +        final class SubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
161.1640 +            SubMapEntryIterator(TreeMap.Entry<K,V> first,
161.1641 +                                TreeMap.Entry<K,V> fence) {
161.1642 +                super(first, fence);
161.1643 +            }
161.1644 +            public Map.Entry<K,V> next() {
161.1645 +                return nextEntry();
161.1646 +            }
161.1647 +            public void remove() {
161.1648 +                removeAscending();
161.1649 +            }
161.1650 +        }
161.1651 +
161.1652 +        final class SubMapKeyIterator extends SubMapIterator<K> {
161.1653 +            SubMapKeyIterator(TreeMap.Entry<K,V> first,
161.1654 +                              TreeMap.Entry<K,V> fence) {
161.1655 +                super(first, fence);
161.1656 +            }
161.1657 +            public K next() {
161.1658 +                return nextEntry().key;
161.1659 +            }
161.1660 +            public void remove() {
161.1661 +                removeAscending();
161.1662 +            }
161.1663 +        }
161.1664 +
161.1665 +        final class DescendingSubMapEntryIterator extends SubMapIterator<Map.Entry<K,V>> {
161.1666 +            DescendingSubMapEntryIterator(TreeMap.Entry<K,V> last,
161.1667 +                                          TreeMap.Entry<K,V> fence) {
161.1668 +                super(last, fence);
161.1669 +            }
161.1670 +
161.1671 +            public Map.Entry<K,V> next() {
161.1672 +                return prevEntry();
161.1673 +            }
161.1674 +            public void remove() {
161.1675 +                removeDescending();
161.1676 +            }
161.1677 +        }
161.1678 +
161.1679 +        final class DescendingSubMapKeyIterator extends SubMapIterator<K> {
161.1680 +            DescendingSubMapKeyIterator(TreeMap.Entry<K,V> last,
161.1681 +                                        TreeMap.Entry<K,V> fence) {
161.1682 +                super(last, fence);
161.1683 +            }
161.1684 +            public K next() {
161.1685 +                return prevEntry().key;
161.1686 +            }
161.1687 +            public void remove() {
161.1688 +                removeDescending();
161.1689 +            }
161.1690 +        }
161.1691 +    }
161.1692 +
161.1693 +    /**
161.1694 +     * @serial include
161.1695 +     */
161.1696 +    static final class AscendingSubMap<K,V> extends NavigableSubMap<K,V> {
161.1697 +        private static final long serialVersionUID = 912986545866124060L;
161.1698 +
161.1699 +        AscendingSubMap(TreeMap<K,V> m,
161.1700 +                        boolean fromStart, K lo, boolean loInclusive,
161.1701 +                        boolean toEnd,     K hi, boolean hiInclusive) {
161.1702 +            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
161.1703 +        }
161.1704 +
161.1705 +        public Comparator<? super K> comparator() {
161.1706 +            return m.comparator();
161.1707 +        }
161.1708 +
161.1709 +        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
161.1710 +                                        K toKey,   boolean toInclusive) {
161.1711 +            if (!inRange(fromKey, fromInclusive))
161.1712 +                throw new IllegalArgumentException("fromKey out of range");
161.1713 +            if (!inRange(toKey, toInclusive))
161.1714 +                throw new IllegalArgumentException("toKey out of range");
161.1715 +            return new AscendingSubMap(m,
161.1716 +                                       false, fromKey, fromInclusive,
161.1717 +                                       false, toKey,   toInclusive);
161.1718 +        }
161.1719 +
161.1720 +        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
161.1721 +            if (!inRange(toKey, inclusive))
161.1722 +                throw new IllegalArgumentException("toKey out of range");
161.1723 +            return new AscendingSubMap(m,
161.1724 +                                       fromStart, lo,    loInclusive,
161.1725 +                                       false,     toKey, inclusive);
161.1726 +        }
161.1727 +
161.1728 +        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
161.1729 +            if (!inRange(fromKey, inclusive))
161.1730 +                throw new IllegalArgumentException("fromKey out of range");
161.1731 +            return new AscendingSubMap(m,
161.1732 +                                       false, fromKey, inclusive,
161.1733 +                                       toEnd, hi,      hiInclusive);
161.1734 +        }
161.1735 +
161.1736 +        public NavigableMap<K,V> descendingMap() {
161.1737 +            NavigableMap<K,V> mv = descendingMapView;
161.1738 +            return (mv != null) ? mv :
161.1739 +                (descendingMapView =
161.1740 +                 new DescendingSubMap(m,
161.1741 +                                      fromStart, lo, loInclusive,
161.1742 +                                      toEnd,     hi, hiInclusive));
161.1743 +        }
161.1744 +
161.1745 +        Iterator<K> keyIterator() {
161.1746 +            return new SubMapKeyIterator(absLowest(), absHighFence());
161.1747 +        }
161.1748 +
161.1749 +        Iterator<K> descendingKeyIterator() {
161.1750 +            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
161.1751 +        }
161.1752 +
161.1753 +        final class AscendingEntrySetView extends EntrySetView {
161.1754 +            public Iterator<Map.Entry<K,V>> iterator() {
161.1755 +                return new SubMapEntryIterator(absLowest(), absHighFence());
161.1756 +            }
161.1757 +        }
161.1758 +
161.1759 +        public Set<Map.Entry<K,V>> entrySet() {
161.1760 +            EntrySetView es = entrySetView;
161.1761 +            return (es != null) ? es : new AscendingEntrySetView();
161.1762 +        }
161.1763 +
161.1764 +        TreeMap.Entry<K,V> subLowest()       { return absLowest(); }
161.1765 +        TreeMap.Entry<K,V> subHighest()      { return absHighest(); }
161.1766 +        TreeMap.Entry<K,V> subCeiling(K key) { return absCeiling(key); }
161.1767 +        TreeMap.Entry<K,V> subHigher(K key)  { return absHigher(key); }
161.1768 +        TreeMap.Entry<K,V> subFloor(K key)   { return absFloor(key); }
161.1769 +        TreeMap.Entry<K,V> subLower(K key)   { return absLower(key); }
161.1770 +    }
161.1771 +
161.1772 +    /**
161.1773 +     * @serial include
161.1774 +     */
161.1775 +    static final class DescendingSubMap<K,V>  extends NavigableSubMap<K,V> {
161.1776 +        private static final long serialVersionUID = 912986545866120460L;
161.1777 +        DescendingSubMap(TreeMap<K,V> m,
161.1778 +                        boolean fromStart, K lo, boolean loInclusive,
161.1779 +                        boolean toEnd,     K hi, boolean hiInclusive) {
161.1780 +            super(m, fromStart, lo, loInclusive, toEnd, hi, hiInclusive);
161.1781 +        }
161.1782 +
161.1783 +        private final Comparator<? super K> reverseComparator =
161.1784 +            Collections.reverseOrder(m.comparator);
161.1785 +
161.1786 +        public Comparator<? super K> comparator() {
161.1787 +            return reverseComparator;
161.1788 +        }
161.1789 +
161.1790 +        public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive,
161.1791 +                                        K toKey,   boolean toInclusive) {
161.1792 +            if (!inRange(fromKey, fromInclusive))
161.1793 +                throw new IllegalArgumentException("fromKey out of range");
161.1794 +            if (!inRange(toKey, toInclusive))
161.1795 +                throw new IllegalArgumentException("toKey out of range");
161.1796 +            return new DescendingSubMap(m,
161.1797 +                                        false, toKey,   toInclusive,
161.1798 +                                        false, fromKey, fromInclusive);
161.1799 +        }
161.1800 +
161.1801 +        public NavigableMap<K,V> headMap(K toKey, boolean inclusive) {
161.1802 +            if (!inRange(toKey, inclusive))
161.1803 +                throw new IllegalArgumentException("toKey out of range");
161.1804 +            return new DescendingSubMap(m,
161.1805 +                                        false, toKey, inclusive,
161.1806 +                                        toEnd, hi,    hiInclusive);
161.1807 +        }
161.1808 +
161.1809 +        public NavigableMap<K,V> tailMap(K fromKey, boolean inclusive) {
161.1810 +            if (!inRange(fromKey, inclusive))
161.1811 +                throw new IllegalArgumentException("fromKey out of range");
161.1812 +            return new DescendingSubMap(m,
161.1813 +                                        fromStart, lo, loInclusive,
161.1814 +                                        false, fromKey, inclusive);
161.1815 +        }
161.1816 +
161.1817 +        public NavigableMap<K,V> descendingMap() {
161.1818 +            NavigableMap<K,V> mv = descendingMapView;
161.1819 +            return (mv != null) ? mv :
161.1820 +                (descendingMapView =
161.1821 +                 new AscendingSubMap(m,
161.1822 +                                     fromStart, lo, loInclusive,
161.1823 +                                     toEnd,     hi, hiInclusive));
161.1824 +        }
161.1825 +
161.1826 +        Iterator<K> keyIterator() {
161.1827 +            return new DescendingSubMapKeyIterator(absHighest(), absLowFence());
161.1828 +        }
161.1829 +
161.1830 +        Iterator<K> descendingKeyIterator() {
161.1831 +            return new SubMapKeyIterator(absLowest(), absHighFence());
161.1832 +        }
161.1833 +
161.1834 +        final class DescendingEntrySetView extends EntrySetView {
161.1835 +            public Iterator<Map.Entry<K,V>> iterator() {
161.1836 +                return new DescendingSubMapEntryIterator(absHighest(), absLowFence());
161.1837 +            }
161.1838 +        }
161.1839 +
161.1840 +        public Set<Map.Entry<K,V>> entrySet() {
161.1841 +            EntrySetView es = entrySetView;
161.1842 +            return (es != null) ? es : new DescendingEntrySetView();
161.1843 +        }
161.1844 +
161.1845 +        TreeMap.Entry<K,V> subLowest()       { return absHighest(); }
161.1846 +        TreeMap.Entry<K,V> subHighest()      { return absLowest(); }
161.1847 +        TreeMap.Entry<K,V> subCeiling(K key) { return absFloor(key); }
161.1848 +        TreeMap.Entry<K,V> subHigher(K key)  { return absLower(key); }
161.1849 +        TreeMap.Entry<K,V> subFloor(K key)   { return absCeiling(key); }
161.1850 +        TreeMap.Entry<K,V> subLower(K key)   { return absHigher(key); }
161.1851 +    }
161.1852 +
161.1853 +    /**
161.1854 +     * This class exists solely for the sake of serialization
161.1855 +     * compatibility with previous releases of TreeMap that did not
161.1856 +     * support NavigableMap.  It translates an old-version SubMap into
161.1857 +     * a new-version AscendingSubMap. This class is never otherwise
161.1858 +     * used.
161.1859 +     *
161.1860 +     * @serial include
161.1861 +     */
161.1862 +    private class SubMap extends AbstractMap<K,V>
161.1863 +        implements SortedMap<K,V>, java.io.Serializable {
161.1864 +        private static final long serialVersionUID = -6520786458950516097L;
161.1865 +        private boolean fromStart = false, toEnd = false;
161.1866 +        private K fromKey, toKey;
161.1867 +        private Object readResolve() {
161.1868 +            return new AscendingSubMap(TreeMap.this,
161.1869 +                                       fromStart, fromKey, true,
161.1870 +                                       toEnd, toKey, false);
161.1871 +        }
161.1872 +        public Set<Map.Entry<K,V>> entrySet() { throw new InternalError(); }
161.1873 +        public K lastKey() { throw new InternalError(); }
161.1874 +        public K firstKey() { throw new InternalError(); }
161.1875 +        public SortedMap<K,V> subMap(K fromKey, K toKey) { throw new InternalError(); }
161.1876 +        public SortedMap<K,V> headMap(K toKey) { throw new InternalError(); }
161.1877 +        public SortedMap<K,V> tailMap(K fromKey) { throw new InternalError(); }
161.1878 +        public Comparator<? super K> comparator() { throw new InternalError(); }
161.1879 +    }
161.1880 +
161.1881 +
161.1882 +    // Red-black mechanics
161.1883 +
161.1884 +    private static final boolean RED   = false;
161.1885 +    private static final boolean BLACK = true;
161.1886 +
161.1887 +    /**
161.1888 +     * Node in the Tree.  Doubles as a means to pass key-value pairs back to
161.1889 +     * user (see Map.Entry).
161.1890 +     */
161.1891 +
161.1892 +    static final class Entry<K,V> implements Map.Entry<K,V> {
161.1893 +        K key;
161.1894 +        V value;
161.1895 +        Entry<K,V> left = null;
161.1896 +        Entry<K,V> right = null;
161.1897 +        Entry<K,V> parent;
161.1898 +        boolean color = BLACK;
161.1899 +
161.1900 +        /**
161.1901 +         * Make a new cell with given key, value, and parent, and with
161.1902 +         * {@code null} child links, and BLACK color.
161.1903 +         */
161.1904 +        Entry(K key, V value, Entry<K,V> parent) {
161.1905 +            this.key = key;
161.1906 +            this.value = value;
161.1907 +            this.parent = parent;
161.1908 +        }
161.1909 +
161.1910 +        /**
161.1911 +         * Returns the key.
161.1912 +         *
161.1913 +         * @return the key
161.1914 +         */
161.1915 +        public K getKey() {
161.1916 +            return key;
161.1917 +        }
161.1918 +
161.1919 +        /**
161.1920 +         * Returns the value associated with the key.
161.1921 +         *
161.1922 +         * @return the value associated with the key
161.1923 +         */
161.1924 +        public V getValue() {
161.1925 +            return value;
161.1926 +        }
161.1927 +
161.1928 +        /**
161.1929 +         * Replaces the value currently associated with the key with the given
161.1930 +         * value.
161.1931 +         *
161.1932 +         * @return the value associated with the key before this method was
161.1933 +         *         called
161.1934 +         */
161.1935 +        public V setValue(V value) {
161.1936 +            V oldValue = this.value;
161.1937 +            this.value = value;
161.1938 +            return oldValue;
161.1939 +        }
161.1940 +
161.1941 +        public boolean equals(Object o) {
161.1942 +            if (!(o instanceof Map.Entry))
161.1943 +                return false;
161.1944 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
161.1945 +
161.1946 +            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
161.1947 +        }
161.1948 +
161.1949 +        public int hashCode() {
161.1950 +            int keyHash = (key==null ? 0 : key.hashCode());
161.1951 +            int valueHash = (value==null ? 0 : value.hashCode());
161.1952 +            return keyHash ^ valueHash;
161.1953 +        }
161.1954 +
161.1955 +        public String toString() {
161.1956 +            return key + "=" + value;
161.1957 +        }
161.1958 +    }
161.1959 +
161.1960 +    /**
161.1961 +     * Returns the first Entry in the TreeMap (according to the TreeMap's
161.1962 +     * key-sort function).  Returns null if the TreeMap is empty.
161.1963 +     */
161.1964 +    final Entry<K,V> getFirstEntry() {
161.1965 +        Entry<K,V> p = root;
161.1966 +        if (p != null)
161.1967 +            while (p.left != null)
161.1968 +                p = p.left;
161.1969 +        return p;
161.1970 +    }
161.1971 +
161.1972 +    /**
161.1973 +     * Returns the last Entry in the TreeMap (according to the TreeMap's
161.1974 +     * key-sort function).  Returns null if the TreeMap is empty.
161.1975 +     */
161.1976 +    final Entry<K,V> getLastEntry() {
161.1977 +        Entry<K,V> p = root;
161.1978 +        if (p != null)
161.1979 +            while (p.right != null)
161.1980 +                p = p.right;
161.1981 +        return p;
161.1982 +    }
161.1983 +
161.1984 +    /**
161.1985 +     * Returns the successor of the specified Entry, or null if no such.
161.1986 +     */
161.1987 +    static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
161.1988 +        if (t == null)
161.1989 +            return null;
161.1990 +        else if (t.right != null) {
161.1991 +            Entry<K,V> p = t.right;
161.1992 +            while (p.left != null)
161.1993 +                p = p.left;
161.1994 +            return p;
161.1995 +        } else {
161.1996 +            Entry<K,V> p = t.parent;
161.1997 +            Entry<K,V> ch = t;
161.1998 +            while (p != null && ch == p.right) {
161.1999 +                ch = p;
161.2000 +                p = p.parent;
161.2001 +            }
161.2002 +            return p;
161.2003 +        }
161.2004 +    }
161.2005 +
161.2006 +    /**
161.2007 +     * Returns the predecessor of the specified Entry, or null if no such.
161.2008 +     */
161.2009 +    static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
161.2010 +        if (t == null)
161.2011 +            return null;
161.2012 +        else if (t.left != null) {
161.2013 +            Entry<K,V> p = t.left;
161.2014 +            while (p.right != null)
161.2015 +                p = p.right;
161.2016 +            return p;
161.2017 +        } else {
161.2018 +            Entry<K,V> p = t.parent;
161.2019 +            Entry<K,V> ch = t;
161.2020 +            while (p != null && ch == p.left) {
161.2021 +                ch = p;
161.2022 +                p = p.parent;
161.2023 +            }
161.2024 +            return p;
161.2025 +        }
161.2026 +    }
161.2027 +
161.2028 +    /**
161.2029 +     * Balancing operations.
161.2030 +     *
161.2031 +     * Implementations of rebalancings during insertion and deletion are
161.2032 +     * slightly different than the CLR version.  Rather than using dummy
161.2033 +     * nilnodes, we use a set of accessors that deal properly with null.  They
161.2034 +     * are used to avoid messiness surrounding nullness checks in the main
161.2035 +     * algorithms.
161.2036 +     */
161.2037 +
161.2038 +    private static <K,V> boolean colorOf(Entry<K,V> p) {
161.2039 +        return (p == null ? BLACK : p.color);
161.2040 +    }
161.2041 +
161.2042 +    private static <K,V> Entry<K,V> parentOf(Entry<K,V> p) {
161.2043 +        return (p == null ? null: p.parent);
161.2044 +    }
161.2045 +
161.2046 +    private static <K,V> void setColor(Entry<K,V> p, boolean c) {
161.2047 +        if (p != null)
161.2048 +            p.color = c;
161.2049 +    }
161.2050 +
161.2051 +    private static <K,V> Entry<K,V> leftOf(Entry<K,V> p) {
161.2052 +        return (p == null) ? null: p.left;
161.2053 +    }
161.2054 +
161.2055 +    private static <K,V> Entry<K,V> rightOf(Entry<K,V> p) {
161.2056 +        return (p == null) ? null: p.right;
161.2057 +    }
161.2058 +
161.2059 +    /** From CLR */
161.2060 +    private void rotateLeft(Entry<K,V> p) {
161.2061 +        if (p != null) {
161.2062 +            Entry<K,V> r = p.right;
161.2063 +            p.right = r.left;
161.2064 +            if (r.left != null)
161.2065 +                r.left.parent = p;
161.2066 +            r.parent = p.parent;
161.2067 +            if (p.parent == null)
161.2068 +                root = r;
161.2069 +            else if (p.parent.left == p)
161.2070 +                p.parent.left = r;
161.2071 +            else
161.2072 +                p.parent.right = r;
161.2073 +            r.left = p;
161.2074 +            p.parent = r;
161.2075 +        }
161.2076 +    }
161.2077 +
161.2078 +    /** From CLR */
161.2079 +    private void rotateRight(Entry<K,V> p) {
161.2080 +        if (p != null) {
161.2081 +            Entry<K,V> l = p.left;
161.2082 +            p.left = l.right;
161.2083 +            if (l.right != null) l.right.parent = p;
161.2084 +            l.parent = p.parent;
161.2085 +            if (p.parent == null)
161.2086 +                root = l;
161.2087 +            else if (p.parent.right == p)
161.2088 +                p.parent.right = l;
161.2089 +            else p.parent.left = l;
161.2090 +            l.right = p;
161.2091 +            p.parent = l;
161.2092 +        }
161.2093 +    }
161.2094 +
161.2095 +    /** From CLR */
161.2096 +    private void fixAfterInsertion(Entry<K,V> x) {
161.2097 +        x.color = RED;
161.2098 +
161.2099 +        while (x != null && x != root && x.parent.color == RED) {
161.2100 +            if (parentOf(x) == leftOf(parentOf(parentOf(x)))) {
161.2101 +                Entry<K,V> y = rightOf(parentOf(parentOf(x)));
161.2102 +                if (colorOf(y) == RED) {
161.2103 +                    setColor(parentOf(x), BLACK);
161.2104 +                    setColor(y, BLACK);
161.2105 +                    setColor(parentOf(parentOf(x)), RED);
161.2106 +                    x = parentOf(parentOf(x));
161.2107 +                } else {
161.2108 +                    if (x == rightOf(parentOf(x))) {
161.2109 +                        x = parentOf(x);
161.2110 +                        rotateLeft(x);
161.2111 +                    }
161.2112 +                    setColor(parentOf(x), BLACK);
161.2113 +                    setColor(parentOf(parentOf(x)), RED);
161.2114 +                    rotateRight(parentOf(parentOf(x)));
161.2115 +                }
161.2116 +            } else {
161.2117 +                Entry<K,V> y = leftOf(parentOf(parentOf(x)));
161.2118 +                if (colorOf(y) == RED) {
161.2119 +                    setColor(parentOf(x), BLACK);
161.2120 +                    setColor(y, BLACK);
161.2121 +                    setColor(parentOf(parentOf(x)), RED);
161.2122 +                    x = parentOf(parentOf(x));
161.2123 +                } else {
161.2124 +                    if (x == leftOf(parentOf(x))) {
161.2125 +                        x = parentOf(x);
161.2126 +                        rotateRight(x);
161.2127 +                    }
161.2128 +                    setColor(parentOf(x), BLACK);
161.2129 +                    setColor(parentOf(parentOf(x)), RED);
161.2130 +                    rotateLeft(parentOf(parentOf(x)));
161.2131 +                }
161.2132 +            }
161.2133 +        }
161.2134 +        root.color = BLACK;
161.2135 +    }
161.2136 +
161.2137 +    /**
161.2138 +     * Delete node p, and then rebalance the tree.
161.2139 +     */
161.2140 +    private void deleteEntry(Entry<K,V> p) {
161.2141 +        modCount++;
161.2142 +        size--;
161.2143 +
161.2144 +        // If strictly internal, copy successor's element to p and then make p
161.2145 +        // point to successor.
161.2146 +        if (p.left != null && p.right != null) {
161.2147 +            Entry<K,V> s = successor(p);
161.2148 +            p.key = s.key;
161.2149 +            p.value = s.value;
161.2150 +            p = s;
161.2151 +        } // p has 2 children
161.2152 +
161.2153 +        // Start fixup at replacement node, if it exists.
161.2154 +        Entry<K,V> replacement = (p.left != null ? p.left : p.right);
161.2155 +
161.2156 +        if (replacement != null) {
161.2157 +            // Link replacement to parent
161.2158 +            replacement.parent = p.parent;
161.2159 +            if (p.parent == null)
161.2160 +                root = replacement;
161.2161 +            else if (p == p.parent.left)
161.2162 +                p.parent.left  = replacement;
161.2163 +            else
161.2164 +                p.parent.right = replacement;
161.2165 +
161.2166 +            // Null out links so they are OK to use by fixAfterDeletion.
161.2167 +            p.left = p.right = p.parent = null;
161.2168 +
161.2169 +            // Fix replacement
161.2170 +            if (p.color == BLACK)
161.2171 +                fixAfterDeletion(replacement);
161.2172 +        } else if (p.parent == null) { // return if we are the only node.
161.2173 +            root = null;
161.2174 +        } else { //  No children. Use self as phantom replacement and unlink.
161.2175 +            if (p.color == BLACK)
161.2176 +                fixAfterDeletion(p);
161.2177 +
161.2178 +            if (p.parent != null) {
161.2179 +                if (p == p.parent.left)
161.2180 +                    p.parent.left = null;
161.2181 +                else if (p == p.parent.right)
161.2182 +                    p.parent.right = null;
161.2183 +                p.parent = null;
161.2184 +            }
161.2185 +        }
161.2186 +    }
161.2187 +
161.2188 +    /** From CLR */
161.2189 +    private void fixAfterDeletion(Entry<K,V> x) {
161.2190 +        while (x != root && colorOf(x) == BLACK) {
161.2191 +            if (x == leftOf(parentOf(x))) {
161.2192 +                Entry<K,V> sib = rightOf(parentOf(x));
161.2193 +
161.2194 +                if (colorOf(sib) == RED) {
161.2195 +                    setColor(sib, BLACK);
161.2196 +                    setColor(parentOf(x), RED);
161.2197 +                    rotateLeft(parentOf(x));
161.2198 +                    sib = rightOf(parentOf(x));
161.2199 +                }
161.2200 +
161.2201 +                if (colorOf(leftOf(sib))  == BLACK &&
161.2202 +                    colorOf(rightOf(sib)) == BLACK) {
161.2203 +                    setColor(sib, RED);
161.2204 +                    x = parentOf(x);
161.2205 +                } else {
161.2206 +                    if (colorOf(rightOf(sib)) == BLACK) {
161.2207 +                        setColor(leftOf(sib), BLACK);
161.2208 +                        setColor(sib, RED);
161.2209 +                        rotateRight(sib);
161.2210 +                        sib = rightOf(parentOf(x));
161.2211 +                    }
161.2212 +                    setColor(sib, colorOf(parentOf(x)));
161.2213 +                    setColor(parentOf(x), BLACK);
161.2214 +                    setColor(rightOf(sib), BLACK);
161.2215 +                    rotateLeft(parentOf(x));
161.2216 +                    x = root;
161.2217 +                }
161.2218 +            } else { // symmetric
161.2219 +                Entry<K,V> sib = leftOf(parentOf(x));
161.2220 +
161.2221 +                if (colorOf(sib) == RED) {
161.2222 +                    setColor(sib, BLACK);
161.2223 +                    setColor(parentOf(x), RED);
161.2224 +                    rotateRight(parentOf(x));
161.2225 +                    sib = leftOf(parentOf(x));
161.2226 +                }
161.2227 +
161.2228 +                if (colorOf(rightOf(sib)) == BLACK &&
161.2229 +                    colorOf(leftOf(sib)) == BLACK) {
161.2230 +                    setColor(sib, RED);
161.2231 +                    x = parentOf(x);
161.2232 +                } else {
161.2233 +                    if (colorOf(leftOf(sib)) == BLACK) {
161.2234 +                        setColor(rightOf(sib), BLACK);
161.2235 +                        setColor(sib, RED);
161.2236 +                        rotateLeft(sib);
161.2237 +                        sib = leftOf(parentOf(x));
161.2238 +                    }
161.2239 +                    setColor(sib, colorOf(parentOf(x)));
161.2240 +                    setColor(parentOf(x), BLACK);
161.2241 +                    setColor(leftOf(sib), BLACK);
161.2242 +                    rotateRight(parentOf(x));
161.2243 +                    x = root;
161.2244 +                }
161.2245 +            }
161.2246 +        }
161.2247 +
161.2248 +        setColor(x, BLACK);
161.2249 +    }
161.2250 +
161.2251 +    private static final long serialVersionUID = 919286545866124006L;
161.2252 +
161.2253 +    /**
161.2254 +     * Save the state of the {@code TreeMap} instance to a stream (i.e.,
161.2255 +     * serialize it).
161.2256 +     *
161.2257 +     * @serialData The <em>size</em> of the TreeMap (the number of key-value
161.2258 +     *             mappings) is emitted (int), followed by the key (Object)
161.2259 +     *             and value (Object) for each key-value mapping represented
161.2260 +     *             by the TreeMap. The key-value mappings are emitted in
161.2261 +     *             key-order (as determined by the TreeMap's Comparator,
161.2262 +     *             or by the keys' natural ordering if the TreeMap has no
161.2263 +     *             Comparator).
161.2264 +     */
161.2265 +    private void writeObject(java.io.ObjectOutputStream s)
161.2266 +        throws java.io.IOException {
161.2267 +        // Write out the Comparator and any hidden stuff
161.2268 +        s.defaultWriteObject();
161.2269 +
161.2270 +        // Write out size (number of Mappings)
161.2271 +        s.writeInt(size);
161.2272 +
161.2273 +        // Write out keys and values (alternating)
161.2274 +        for (Iterator<Map.Entry<K,V>> i = entrySet().iterator(); i.hasNext(); ) {
161.2275 +            Map.Entry<K,V> e = i.next();
161.2276 +            s.writeObject(e.getKey());
161.2277 +            s.writeObject(e.getValue());
161.2278 +        }
161.2279 +    }
161.2280 +
161.2281 +    /**
161.2282 +     * Reconstitute the {@code TreeMap} instance from a stream (i.e.,
161.2283 +     * deserialize it).
161.2284 +     */
161.2285 +    private void readObject(final java.io.ObjectInputStream s)
161.2286 +        throws java.io.IOException, ClassNotFoundException {
161.2287 +        // Read in the Comparator and any hidden stuff
161.2288 +        s.defaultReadObject();
161.2289 +
161.2290 +        // Read in size
161.2291 +        int size = s.readInt();
161.2292 +
161.2293 +        buildFromSorted(size, null, s, null);
161.2294 +    }
161.2295 +
161.2296 +    /** Intended to be called only from TreeSet.readObject */
161.2297 +    void readTreeSet(int size, java.io.ObjectInputStream s, V defaultVal)
161.2298 +        throws java.io.IOException, ClassNotFoundException {
161.2299 +        buildFromSorted(size, null, s, defaultVal);
161.2300 +    }
161.2301 +
161.2302 +    /** Intended to be called only from TreeSet.addAll */
161.2303 +    void addAllForTreeSet(SortedSet<? extends K> set, V defaultVal) {
161.2304 +        try {
161.2305 +            buildFromSorted(set.size(), set.iterator(), null, defaultVal);
161.2306 +        } catch (java.io.IOException cannotHappen) {
161.2307 +        } catch (ClassNotFoundException cannotHappen) {
161.2308 +        }
161.2309 +    }
161.2310 +
161.2311 +
161.2312 +    /**
161.2313 +     * Linear time tree building algorithm from sorted data.  Can accept keys
161.2314 +     * and/or values from iterator or stream. This leads to too many
161.2315 +     * parameters, but seems better than alternatives.  The four formats
161.2316 +     * that this method accepts are:
161.2317 +     *
161.2318 +     *    1) An iterator of Map.Entries.  (it != null, defaultVal == null).
161.2319 +     *    2) An iterator of keys.         (it != null, defaultVal != null).
161.2320 +     *    3) A stream of alternating serialized keys and values.
161.2321 +     *                                   (it == null, defaultVal == null).
161.2322 +     *    4) A stream of serialized keys. (it == null, defaultVal != null).
161.2323 +     *
161.2324 +     * It is assumed that the comparator of the TreeMap is already set prior
161.2325 +     * to calling this method.
161.2326 +     *
161.2327 +     * @param size the number of keys (or key-value pairs) to be read from
161.2328 +     *        the iterator or stream
161.2329 +     * @param it If non-null, new entries are created from entries
161.2330 +     *        or keys read from this iterator.
161.2331 +     * @param str If non-null, new entries are created from keys and
161.2332 +     *        possibly values read from this stream in serialized form.
161.2333 +     *        Exactly one of it and str should be non-null.
161.2334 +     * @param defaultVal if non-null, this default value is used for
161.2335 +     *        each value in the map.  If null, each value is read from
161.2336 +     *        iterator or stream, as described above.
161.2337 +     * @throws IOException propagated from stream reads. This cannot
161.2338 +     *         occur if str is null.
161.2339 +     * @throws ClassNotFoundException propagated from readObject.
161.2340 +     *         This cannot occur if str is null.
161.2341 +     */
161.2342 +    private void buildFromSorted(int size, Iterator it,
161.2343 +                                 java.io.ObjectInputStream str,
161.2344 +                                 V defaultVal)
161.2345 +        throws  java.io.IOException, ClassNotFoundException {
161.2346 +        this.size = size;
161.2347 +        root = buildFromSorted(0, 0, size-1, computeRedLevel(size),
161.2348 +                               it, str, defaultVal);
161.2349 +    }
161.2350 +
161.2351 +    /**
161.2352 +     * Recursive "helper method" that does the real work of the
161.2353 +     * previous method.  Identically named parameters have
161.2354 +     * identical definitions.  Additional parameters are documented below.
161.2355 +     * It is assumed that the comparator and size fields of the TreeMap are
161.2356 +     * already set prior to calling this method.  (It ignores both fields.)
161.2357 +     *
161.2358 +     * @param level the current level of tree. Initial call should be 0.
161.2359 +     * @param lo the first element index of this subtree. Initial should be 0.
161.2360 +     * @param hi the last element index of this subtree.  Initial should be
161.2361 +     *        size-1.
161.2362 +     * @param redLevel the level at which nodes should be red.
161.2363 +     *        Must be equal to computeRedLevel for tree of this size.
161.2364 +     */
161.2365 +    private final Entry<K,V> buildFromSorted(int level, int lo, int hi,
161.2366 +                                             int redLevel,
161.2367 +                                             Iterator it,
161.2368 +                                             java.io.ObjectInputStream str,
161.2369 +                                             V defaultVal)
161.2370 +        throws  java.io.IOException, ClassNotFoundException {
161.2371 +        /*
161.2372 +         * Strategy: The root is the middlemost element. To get to it, we
161.2373 +         * have to first recursively construct the entire left subtree,
161.2374 +         * so as to grab all of its elements. We can then proceed with right
161.2375 +         * subtree.
161.2376 +         *
161.2377 +         * The lo and hi arguments are the minimum and maximum
161.2378 +         * indices to pull out of the iterator or stream for current subtree.
161.2379 +         * They are not actually indexed, we just proceed sequentially,
161.2380 +         * ensuring that items are extracted in corresponding order.
161.2381 +         */
161.2382 +
161.2383 +        if (hi < lo) return null;
161.2384 +
161.2385 +        int mid = (lo + hi) >>> 1;
161.2386 +
161.2387 +        Entry<K,V> left  = null;
161.2388 +        if (lo < mid)
161.2389 +            left = buildFromSorted(level+1, lo, mid - 1, redLevel,
161.2390 +                                   it, str, defaultVal);
161.2391 +
161.2392 +        // extract key and/or value from iterator or stream
161.2393 +        K key;
161.2394 +        V value;
161.2395 +        if (it != null) {
161.2396 +            if (defaultVal==null) {
161.2397 +                Map.Entry<K,V> entry = (Map.Entry<K,V>)it.next();
161.2398 +                key = entry.getKey();
161.2399 +                value = entry.getValue();
161.2400 +            } else {
161.2401 +                key = (K)it.next();
161.2402 +                value = defaultVal;
161.2403 +            }
161.2404 +        } else { // use stream
161.2405 +            key = (K) str.readObject();
161.2406 +            value = (defaultVal != null ? defaultVal : (V) str.readObject());
161.2407 +        }
161.2408 +
161.2409 +        Entry<K,V> middle =  new Entry<>(key, value, null);
161.2410 +
161.2411 +        // color nodes in non-full bottommost level red
161.2412 +        if (level == redLevel)
161.2413 +            middle.color = RED;
161.2414 +
161.2415 +        if (left != null) {
161.2416 +            middle.left = left;
161.2417 +            left.parent = middle;
161.2418 +        }
161.2419 +
161.2420 +        if (mid < hi) {
161.2421 +            Entry<K,V> right = buildFromSorted(level+1, mid+1, hi, redLevel,
161.2422 +                                               it, str, defaultVal);
161.2423 +            middle.right = right;
161.2424 +            right.parent = middle;
161.2425 +        }
161.2426 +
161.2427 +        return middle;
161.2428 +    }
161.2429 +
161.2430 +    /**
161.2431 +     * Find the level down to which to assign all nodes BLACK.  This is the
161.2432 +     * last `full' level of the complete binary tree produced by
161.2433 +     * buildTree. The remaining nodes are colored RED. (This makes a `nice'
161.2434 +     * set of color assignments wrt future insertions.) This level number is
161.2435 +     * computed by finding the number of splits needed to reach the zeroeth
161.2436 +     * node.  (The answer is ~lg(N), but in any case must be computed by same
161.2437 +     * quick O(lg(N)) loop.)
161.2438 +     */
161.2439 +    private static int computeRedLevel(int sz) {
161.2440 +        int level = 0;
161.2441 +        for (int m = sz - 1; m >= 0; m = m / 2 - 1)
161.2442 +            level++;
161.2443 +        return level;
161.2444 +    }
161.2445 +}
   162.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   162.2 +++ b/rt/emul/compact/src/main/java/java/util/TreeSet.java	Mon Oct 07 14:20:58 2013 +0200
   162.3 @@ -0,0 +1,539 @@
   162.4 +/*
   162.5 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
   162.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   162.7 + *
   162.8 + * This code is free software; you can redistribute it and/or modify it
   162.9 + * under the terms of the GNU General Public License version 2 only, as
  162.10 + * published by the Free Software Foundation.  Oracle designates this
  162.11 + * particular file as subject to the "Classpath" exception as provided
  162.12 + * by Oracle in the LICENSE file that accompanied this code.
  162.13 + *
  162.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  162.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  162.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  162.17 + * version 2 for more details (a copy is included in the LICENSE file that
  162.18 + * accompanied this code).
  162.19 + *
  162.20 + * You should have received a copy of the GNU General Public License version
  162.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  162.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  162.23 + *
  162.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  162.25 + * or visit www.oracle.com if you need additional information or have any
  162.26 + * questions.
  162.27 + */
  162.28 +
  162.29 +package java.util;
  162.30 +
  162.31 +/**
  162.32 + * A {@link NavigableSet} implementation based on a {@link TreeMap}.
  162.33 + * The elements are ordered using their {@linkplain Comparable natural
  162.34 + * ordering}, or by a {@link Comparator} provided at set creation
  162.35 + * time, depending on which constructor is used.
  162.36 + *
  162.37 + * <p>This implementation provides guaranteed log(n) time cost for the basic
  162.38 + * operations ({@code add}, {@code remove} and {@code contains}).
  162.39 + *
  162.40 + * <p>Note that the ordering maintained by a set (whether or not an explicit
  162.41 + * comparator is provided) must be <i>consistent with equals</i> if it is to
  162.42 + * correctly implement the {@code Set} interface.  (See {@code Comparable}
  162.43 + * or {@code Comparator} for a precise definition of <i>consistent with
  162.44 + * equals</i>.)  This is so because the {@code Set} interface is defined in
  162.45 + * terms of the {@code equals} operation, but a {@code TreeSet} instance
  162.46 + * performs all element comparisons using its {@code compareTo} (or
  162.47 + * {@code compare}) method, so two elements that are deemed equal by this method
  162.48 + * are, from the standpoint of the set, equal.  The behavior of a set
  162.49 + * <i>is</i> well-defined even if its ordering is inconsistent with equals; it
  162.50 + * just fails to obey the general contract of the {@code Set} interface.
  162.51 + *
  162.52 + * <p><strong>Note that this implementation is not synchronized.</strong>
  162.53 + * If multiple threads access a tree set concurrently, and at least one
  162.54 + * of the threads modifies the set, it <i>must</i> be synchronized
  162.55 + * externally.  This is typically accomplished by synchronizing on some
  162.56 + * object that naturally encapsulates the set.
  162.57 + * If no such object exists, the set should be "wrapped" using the
  162.58 + * {@link Collections#synchronizedSortedSet Collections.synchronizedSortedSet}
  162.59 + * method.  This is best done at creation time, to prevent accidental
  162.60 + * unsynchronized access to the set: <pre>
  162.61 + *   SortedSet s = Collections.synchronizedSortedSet(new TreeSet(...));</pre>
  162.62 + *
  162.63 + * <p>The iterators returned by this class's {@code iterator} method are
  162.64 + * <i>fail-fast</i>: if the set is modified at any time after the iterator is
  162.65 + * created, in any way except through the iterator's own {@code remove}
  162.66 + * method, the iterator will throw a {@link ConcurrentModificationException}.
  162.67 + * Thus, in the face of concurrent modification, the iterator fails quickly
  162.68 + * and cleanly, rather than risking arbitrary, non-deterministic behavior at
  162.69 + * an undetermined time in the future.
  162.70 + *
  162.71 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
  162.72 + * as it is, generally speaking, impossible to make any hard guarantees in the
  162.73 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
  162.74 + * throw {@code ConcurrentModificationException} on a best-effort basis.
  162.75 + * Therefore, it would be wrong to write a program that depended on this
  162.76 + * exception for its correctness:   <i>the fail-fast behavior of iterators
  162.77 + * should be used only to detect bugs.</i>
  162.78 + *
  162.79 + * <p>This class is a member of the
  162.80 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
  162.81 + * Java Collections Framework</a>.
  162.82 + *
  162.83 + * @param <E> the type of elements maintained by this set
  162.84 + *
  162.85 + * @author  Josh Bloch
  162.86 + * @see     Collection
  162.87 + * @see     Set
  162.88 + * @see     HashSet
  162.89 + * @see     Comparable
  162.90 + * @see     Comparator
  162.91 + * @see     TreeMap
  162.92 + * @since   1.2
  162.93 + */
  162.94 +
  162.95 +public class TreeSet<E> extends AbstractSet<E>
  162.96 +    implements NavigableSet<E>, Cloneable, java.io.Serializable
  162.97 +{
  162.98 +    /**
  162.99 +     * The backing map.
 162.100 +     */
 162.101 +    private transient NavigableMap<E,Object> m;
 162.102 +
 162.103 +    // Dummy value to associate with an Object in the backing Map
 162.104 +    private static final Object PRESENT = new Object();
 162.105 +
 162.106 +    /**
 162.107 +     * Constructs a set backed by the specified navigable map.
 162.108 +     */
 162.109 +    TreeSet(NavigableMap<E,Object> m) {
 162.110 +        this.m = m;
 162.111 +    }
 162.112 +
 162.113 +    /**
 162.114 +     * Constructs a new, empty tree set, sorted according to the
 162.115 +     * natural ordering of its elements.  All elements inserted into
 162.116 +     * the set must implement the {@link Comparable} interface.
 162.117 +     * Furthermore, all such elements must be <i>mutually
 162.118 +     * comparable</i>: {@code e1.compareTo(e2)} must not throw a
 162.119 +     * {@code ClassCastException} for any elements {@code e1} and
 162.120 +     * {@code e2} in the set.  If the user attempts to add an element
 162.121 +     * to the set that violates this constraint (for example, the user
 162.122 +     * attempts to add a string element to a set whose elements are
 162.123 +     * integers), the {@code add} call will throw a
 162.124 +     * {@code ClassCastException}.
 162.125 +     */
 162.126 +    public TreeSet() {
 162.127 +        this(new TreeMap<E,Object>());
 162.128 +    }
 162.129 +
 162.130 +    /**
 162.131 +     * Constructs a new, empty tree set, sorted according to the specified
 162.132 +     * comparator.  All elements inserted into the set must be <i>mutually
 162.133 +     * comparable</i> by the specified comparator: {@code comparator.compare(e1,
 162.134 +     * e2)} must not throw a {@code ClassCastException} for any elements
 162.135 +     * {@code e1} and {@code e2} in the set.  If the user attempts to add
 162.136 +     * an element to the set that violates this constraint, the
 162.137 +     * {@code add} call will throw a {@code ClassCastException}.
 162.138 +     *
 162.139 +     * @param comparator the comparator that will be used to order this set.
 162.140 +     *        If {@code null}, the {@linkplain Comparable natural
 162.141 +     *        ordering} of the elements will be used.
 162.142 +     */
 162.143 +    public TreeSet(Comparator<? super E> comparator) {
 162.144 +        this(new TreeMap<>(comparator));
 162.145 +    }
 162.146 +
 162.147 +    /**
 162.148 +     * Constructs a new tree set containing the elements in the specified
 162.149 +     * collection, sorted according to the <i>natural ordering</i> of its
 162.150 +     * elements.  All elements inserted into the set must implement the
 162.151 +     * {@link Comparable} interface.  Furthermore, all such elements must be
 162.152 +     * <i>mutually comparable</i>: {@code e1.compareTo(e2)} must not throw a
 162.153 +     * {@code ClassCastException} for any elements {@code e1} and
 162.154 +     * {@code e2} in the set.
 162.155 +     *
 162.156 +     * @param c collection whose elements will comprise the new set
 162.157 +     * @throws ClassCastException if the elements in {@code c} are
 162.158 +     *         not {@link Comparable}, or are not mutually comparable
 162.159 +     * @throws NullPointerException if the specified collection is null
 162.160 +     */
 162.161 +    public TreeSet(Collection<? extends E> c) {
 162.162 +        this();
 162.163 +        addAll(c);
 162.164 +    }
 162.165 +
 162.166 +    /**
 162.167 +     * Constructs a new tree set containing the same elements and
 162.168 +     * using the same ordering as the specified sorted set.
 162.169 +     *
 162.170 +     * @param s sorted set whose elements will comprise the new set
 162.171 +     * @throws NullPointerException if the specified sorted set is null
 162.172 +     */
 162.173 +    public TreeSet(SortedSet<E> s) {
 162.174 +        this(s.comparator());
 162.175 +        addAll(s);
 162.176 +    }
 162.177 +
 162.178 +    /**
 162.179 +     * Returns an iterator over the elements in this set in ascending order.
 162.180 +     *
 162.181 +     * @return an iterator over the elements in this set in ascending order
 162.182 +     */
 162.183 +    public Iterator<E> iterator() {
 162.184 +        return m.navigableKeySet().iterator();
 162.185 +    }
 162.186 +
 162.187 +    /**
 162.188 +     * Returns an iterator over the elements in this set in descending order.
 162.189 +     *
 162.190 +     * @return an iterator over the elements in this set in descending order
 162.191 +     * @since 1.6
 162.192 +     */
 162.193 +    public Iterator<E> descendingIterator() {
 162.194 +        return m.descendingKeySet().iterator();
 162.195 +    }
 162.196 +
 162.197 +    /**
 162.198 +     * @since 1.6
 162.199 +     */
 162.200 +    public NavigableSet<E> descendingSet() {
 162.201 +        return new TreeSet<>(m.descendingMap());
 162.202 +    }
 162.203 +
 162.204 +    /**
 162.205 +     * Returns the number of elements in this set (its cardinality).
 162.206 +     *
 162.207 +     * @return the number of elements in this set (its cardinality)
 162.208 +     */
 162.209 +    public int size() {
 162.210 +        return m.size();
 162.211 +    }
 162.212 +
 162.213 +    /**
 162.214 +     * Returns {@code true} if this set contains no elements.
 162.215 +     *
 162.216 +     * @return {@code true} if this set contains no elements
 162.217 +     */
 162.218 +    public boolean isEmpty() {
 162.219 +        return m.isEmpty();
 162.220 +    }
 162.221 +
 162.222 +    /**
 162.223 +     * Returns {@code true} if this set contains the specified element.
 162.224 +     * More formally, returns {@code true} if and only if this set
 162.225 +     * contains an element {@code e} such that
 162.226 +     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
 162.227 +     *
 162.228 +     * @param o object to be checked for containment in this set
 162.229 +     * @return {@code true} if this set contains the specified element
 162.230 +     * @throws ClassCastException if the specified object cannot be compared
 162.231 +     *         with the elements currently in the set
 162.232 +     * @throws NullPointerException if the specified element is null
 162.233 +     *         and this set uses natural ordering, or its comparator
 162.234 +     *         does not permit null elements
 162.235 +     */
 162.236 +    public boolean contains(Object o) {
 162.237 +        return m.containsKey(o);
 162.238 +    }
 162.239 +
 162.240 +    /**
 162.241 +     * Adds the specified element to this set if it is not already present.
 162.242 +     * More formally, adds the specified element {@code e} to this set if
 162.243 +     * the set contains no element {@code e2} such that
 162.244 +     * <tt>(e==null&nbsp;?&nbsp;e2==null&nbsp;:&nbsp;e.equals(e2))</tt>.
 162.245 +     * If this set already contains the element, the call leaves the set
 162.246 +     * unchanged and returns {@code false}.
 162.247 +     *
 162.248 +     * @param e element to be added to this set
 162.249 +     * @return {@code true} if this set did not already contain the specified
 162.250 +     *         element
 162.251 +     * @throws ClassCastException if the specified object cannot be compared
 162.252 +     *         with the elements currently in this set
 162.253 +     * @throws NullPointerException if the specified element is null
 162.254 +     *         and this set uses natural ordering, or its comparator
 162.255 +     *         does not permit null elements
 162.256 +     */
 162.257 +    public boolean add(E e) {
 162.258 +        return m.put(e, PRESENT)==null;
 162.259 +    }
 162.260 +
 162.261 +    /**
 162.262 +     * Removes the specified element from this set if it is present.
 162.263 +     * More formally, removes an element {@code e} such that
 162.264 +     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>,
 162.265 +     * if this set contains such an element.  Returns {@code true} if
 162.266 +     * this set contained the element (or equivalently, if this set
 162.267 +     * changed as a result of the call).  (This set will not contain the
 162.268 +     * element once the call returns.)
 162.269 +     *
 162.270 +     * @param o object to be removed from this set, if present
 162.271 +     * @return {@code true} if this set contained the specified element
 162.272 +     * @throws ClassCastException if the specified object cannot be compared
 162.273 +     *         with the elements currently in this set
 162.274 +     * @throws NullPointerException if the specified element is null
 162.275 +     *         and this set uses natural ordering, or its comparator
 162.276 +     *         does not permit null elements
 162.277 +     */
 162.278 +    public boolean remove(Object o) {
 162.279 +        return m.remove(o)==PRESENT;
 162.280 +    }
 162.281 +
 162.282 +    /**
 162.283 +     * Removes all of the elements from this set.
 162.284 +     * The set will be empty after this call returns.
 162.285 +     */
 162.286 +    public void clear() {
 162.287 +        m.clear();
 162.288 +    }
 162.289 +
 162.290 +    /**
 162.291 +     * Adds all of the elements in the specified collection to this set.
 162.292 +     *
 162.293 +     * @param c collection containing elements to be added to this set
 162.294 +     * @return {@code true} if this set changed as a result of the call
 162.295 +     * @throws ClassCastException if the elements provided cannot be compared
 162.296 +     *         with the elements currently in the set
 162.297 +     * @throws NullPointerException if the specified collection is null or
 162.298 +     *         if any element is null and this set uses natural ordering, or
 162.299 +     *         its comparator does not permit null elements
 162.300 +     */
 162.301 +    public  boolean addAll(Collection<? extends E> c) {
 162.302 +        // Use linear-time version if applicable
 162.303 +        if (m.size()==0 && c.size() > 0 &&
 162.304 +            c instanceof SortedSet &&
 162.305 +            m instanceof TreeMap) {
 162.306 +            SortedSet<? extends E> set = (SortedSet<? extends E>) c;
 162.307 +            TreeMap<E,Object> map = (TreeMap<E, Object>) m;
 162.308 +            Comparator<? super E> cc = (Comparator<? super E>) set.comparator();
 162.309 +            Comparator<? super E> mc = map.comparator();
 162.310 +            if (cc==mc || (cc != null && cc.equals(mc))) {
 162.311 +                map.addAllForTreeSet(set, PRESENT);
 162.312 +                return true;
 162.313 +            }
 162.314 +        }
 162.315 +        return super.addAll(c);
 162.316 +    }
 162.317 +
 162.318 +    /**
 162.319 +     * @throws ClassCastException {@inheritDoc}
 162.320 +     * @throws NullPointerException if {@code fromElement} or {@code toElement}
 162.321 +     *         is null and this set uses natural ordering, or its comparator
 162.322 +     *         does not permit null elements
 162.323 +     * @throws IllegalArgumentException {@inheritDoc}
 162.324 +     * @since 1.6
 162.325 +     */
 162.326 +    public NavigableSet<E> subSet(E fromElement, boolean fromInclusive,
 162.327 +                                  E toElement,   boolean toInclusive) {
 162.328 +        return new TreeSet<>(m.subMap(fromElement, fromInclusive,
 162.329 +                                       toElement,   toInclusive));
 162.330 +    }
 162.331 +
 162.332 +    /**
 162.333 +     * @throws ClassCastException {@inheritDoc}
 162.334 +     * @throws NullPointerException if {@code toElement} is null and
 162.335 +     *         this set uses natural ordering, or its comparator does
 162.336 +     *         not permit null elements
 162.337 +     * @throws IllegalArgumentException {@inheritDoc}
 162.338 +     * @since 1.6
 162.339 +     */
 162.340 +    public NavigableSet<E> headSet(E toElement, boolean inclusive) {
 162.341 +        return new TreeSet<>(m.headMap(toElement, inclusive));
 162.342 +    }
 162.343 +
 162.344 +    /**
 162.345 +     * @throws ClassCastException {@inheritDoc}
 162.346 +     * @throws NullPointerException if {@code fromElement} is null and
 162.347 +     *         this set uses natural ordering, or its comparator does
 162.348 +     *         not permit null elements
 162.349 +     * @throws IllegalArgumentException {@inheritDoc}
 162.350 +     * @since 1.6
 162.351 +     */
 162.352 +    public NavigableSet<E> tailSet(E fromElement, boolean inclusive) {
 162.353 +        return new TreeSet<>(m.tailMap(fromElement, inclusive));
 162.354 +    }
 162.355 +
 162.356 +    /**
 162.357 +     * @throws ClassCastException {@inheritDoc}
 162.358 +     * @throws NullPointerException if {@code fromElement} or
 162.359 +     *         {@code toElement} is null and this set uses natural ordering,
 162.360 +     *         or its comparator does not permit null elements
 162.361 +     * @throws IllegalArgumentException {@inheritDoc}
 162.362 +     */
 162.363 +    public SortedSet<E> subSet(E fromElement, E toElement) {
 162.364 +        return subSet(fromElement, true, toElement, false);
 162.365 +    }
 162.366 +
 162.367 +    /**
 162.368 +     * @throws ClassCastException {@inheritDoc}
 162.369 +     * @throws NullPointerException if {@code toElement} is null
 162.370 +     *         and this set uses natural ordering, or its comparator does
 162.371 +     *         not permit null elements
 162.372 +     * @throws IllegalArgumentException {@inheritDoc}
 162.373 +     */
 162.374 +    public SortedSet<E> headSet(E toElement) {
 162.375 +        return headSet(toElement, false);
 162.376 +    }
 162.377 +
 162.378 +    /**
 162.379 +     * @throws ClassCastException {@inheritDoc}
 162.380 +     * @throws NullPointerException if {@code fromElement} is null
 162.381 +     *         and this set uses natural ordering, or its comparator does
 162.382 +     *         not permit null elements
 162.383 +     * @throws IllegalArgumentException {@inheritDoc}
 162.384 +     */
 162.385 +    public SortedSet<E> tailSet(E fromElement) {
 162.386 +        return tailSet(fromElement, true);
 162.387 +    }
 162.388 +
 162.389 +    public Comparator<? super E> comparator() {
 162.390 +        return m.comparator();
 162.391 +    }
 162.392 +
 162.393 +    /**
 162.394 +     * @throws NoSuchElementException {@inheritDoc}
 162.395 +     */
 162.396 +    public E first() {
 162.397 +        return m.firstKey();
 162.398 +    }
 162.399 +
 162.400 +    /**
 162.401 +     * @throws NoSuchElementException {@inheritDoc}
 162.402 +     */
 162.403 +    public E last() {
 162.404 +        return m.lastKey();
 162.405 +    }
 162.406 +
 162.407 +    // NavigableSet API methods
 162.408 +
 162.409 +    /**
 162.410 +     * @throws ClassCastException {@inheritDoc}
 162.411 +     * @throws NullPointerException if the specified element is null
 162.412 +     *         and this set uses natural ordering, or its comparator
 162.413 +     *         does not permit null elements
 162.414 +     * @since 1.6
 162.415 +     */
 162.416 +    public E lower(E e) {
 162.417 +        return m.lowerKey(e);
 162.418 +    }
 162.419 +
 162.420 +    /**
 162.421 +     * @throws ClassCastException {@inheritDoc}
 162.422 +     * @throws NullPointerException if the specified element is null
 162.423 +     *         and this set uses natural ordering, or its comparator
 162.424 +     *         does not permit null elements
 162.425 +     * @since 1.6
 162.426 +     */
 162.427 +    public E floor(E e) {
 162.428 +        return m.floorKey(e);
 162.429 +    }
 162.430 +
 162.431 +    /**
 162.432 +     * @throws ClassCastException {@inheritDoc}
 162.433 +     * @throws NullPointerException if the specified element is null
 162.434 +     *         and this set uses natural ordering, or its comparator
 162.435 +     *         does not permit null elements
 162.436 +     * @since 1.6
 162.437 +     */
 162.438 +    public E ceiling(E e) {
 162.439 +        return m.ceilingKey(e);
 162.440 +    }
 162.441 +
 162.442 +    /**
 162.443 +     * @throws ClassCastException {@inheritDoc}
 162.444 +     * @throws NullPointerException if the specified element is null
 162.445 +     *         and this set uses natural ordering, or its comparator
 162.446 +     *         does not permit null elements
 162.447 +     * @since 1.6
 162.448 +     */
 162.449 +    public E higher(E e) {
 162.450 +        return m.higherKey(e);
 162.451 +    }
 162.452 +
 162.453 +    /**
 162.454 +     * @since 1.6
 162.455 +     */
 162.456 +    public E pollFirst() {
 162.457 +        Map.Entry<E,?> e = m.pollFirstEntry();
 162.458 +        return (e == null) ? null : e.getKey();
 162.459 +    }
 162.460 +
 162.461 +    /**
 162.462 +     * @since 1.6
 162.463 +     */
 162.464 +    public E pollLast() {
 162.465 +        Map.Entry<E,?> e = m.pollLastEntry();
 162.466 +        return (e == null) ? null : e.getKey();
 162.467 +    }
 162.468 +
 162.469 +    /**
 162.470 +     * Returns a shallow copy of this {@code TreeSet} instance. (The elements
 162.471 +     * themselves are not cloned.)
 162.472 +     *
 162.473 +     * @return a shallow copy of this set
 162.474 +     */
 162.475 +    public Object clone() {
 162.476 +        TreeSet<E> clone = null;
 162.477 +        try {
 162.478 +            clone = (TreeSet<E>) super.clone();
 162.479 +        } catch (CloneNotSupportedException e) {
 162.480 +            throw new InternalError();
 162.481 +        }
 162.482 +
 162.483 +        clone.m = new TreeMap<>(m);
 162.484 +        return clone;
 162.485 +    }
 162.486 +
 162.487 +    /**
 162.488 +     * Save the state of the {@code TreeSet} instance to a stream (that is,
 162.489 +     * serialize it).
 162.490 +     *
 162.491 +     * @serialData Emits the comparator used to order this set, or
 162.492 +     *             {@code null} if it obeys its elements' natural ordering
 162.493 +     *             (Object), followed by the size of the set (the number of
 162.494 +     *             elements it contains) (int), followed by all of its
 162.495 +     *             elements (each an Object) in order (as determined by the
 162.496 +     *             set's Comparator, or by the elements' natural ordering if
 162.497 +     *             the set has no Comparator).
 162.498 +     */
 162.499 +    private void writeObject(java.io.ObjectOutputStream s)
 162.500 +        throws java.io.IOException {
 162.501 +        // Write out any hidden stuff
 162.502 +        s.defaultWriteObject();
 162.503 +
 162.504 +        // Write out Comparator
 162.505 +        s.writeObject(m.comparator());
 162.506 +
 162.507 +        // Write out size
 162.508 +        s.writeInt(m.size());
 162.509 +
 162.510 +        // Write out all elements in the proper order.
 162.511 +        for (E e : m.keySet())
 162.512 +            s.writeObject(e);
 162.513 +    }
 162.514 +
 162.515 +    /**
 162.516 +     * Reconstitute the {@code TreeSet} instance from a stream (that is,
 162.517 +     * deserialize it).
 162.518 +     */
 162.519 +    private void readObject(java.io.ObjectInputStream s)
 162.520 +        throws java.io.IOException, ClassNotFoundException {
 162.521 +        // Read in any hidden stuff
 162.522 +        s.defaultReadObject();
 162.523 +
 162.524 +        // Read in Comparator
 162.525 +        Comparator<? super E> c = (Comparator<? super E>) s.readObject();
 162.526 +
 162.527 +        // Create backing TreeMap
 162.528 +        TreeMap<E,Object> tm;
 162.529 +        if (c==null)
 162.530 +            tm = new TreeMap<>();
 162.531 +        else
 162.532 +            tm = new TreeMap<>(c);
 162.533 +        m = tm;
 162.534 +
 162.535 +        // Read in size
 162.536 +        int size = s.readInt();
 162.537 +
 162.538 +        tm.readTreeSet(size, s, PRESENT);
 162.539 +    }
 162.540 +
 162.541 +    private static final long serialVersionUID = -2479143000061671589L;
 162.542 +}
   163.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   163.2 +++ b/rt/emul/compact/src/main/java/java/util/WeakHashMap.java	Mon Oct 07 14:20:58 2013 +0200
   163.3 @@ -0,0 +1,972 @@
   163.4 +/*
   163.5 + * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
   163.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   163.7 + *
   163.8 + * This code is free software; you can redistribute it and/or modify it
   163.9 + * under the terms of the GNU General Public License version 2 only, as
  163.10 + * published by the Free Software Foundation.  Oracle designates this
  163.11 + * particular file as subject to the "Classpath" exception as provided
  163.12 + * by Oracle in the LICENSE file that accompanied this code.
  163.13 + *
  163.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  163.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  163.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  163.17 + * version 2 for more details (a copy is included in the LICENSE file that
  163.18 + * accompanied this code).
  163.19 + *
  163.20 + * You should have received a copy of the GNU General Public License version
  163.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  163.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  163.23 + *
  163.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  163.25 + * or visit www.oracle.com if you need additional information or have any
  163.26 + * questions.
  163.27 + */
  163.28 +
  163.29 +package java.util;
  163.30 +import java.lang.ref.WeakReference;
  163.31 +import java.lang.ref.ReferenceQueue;
  163.32 +
  163.33 +
  163.34 +/**
  163.35 + * Hash table based implementation of the <tt>Map</tt> interface, with
  163.36 + * <em>weak keys</em>.
  163.37 + * An entry in a <tt>WeakHashMap</tt> will automatically be removed when
  163.38 + * its key is no longer in ordinary use.  More precisely, the presence of a
  163.39 + * mapping for a given key will not prevent the key from being discarded by the
  163.40 + * garbage collector, that is, made finalizable, finalized, and then reclaimed.
  163.41 + * When a key has been discarded its entry is effectively removed from the map,
  163.42 + * so this class behaves somewhat differently from other <tt>Map</tt>
  163.43 + * implementations.
  163.44 + *
  163.45 + * <p> Both null values and the null key are supported. This class has
  163.46 + * performance characteristics similar to those of the <tt>HashMap</tt>
  163.47 + * class, and has the same efficiency parameters of <em>initial capacity</em>
  163.48 + * and <em>load factor</em>.
  163.49 + *
  163.50 + * <p> Like most collection classes, this class is not synchronized.
  163.51 + * A synchronized <tt>WeakHashMap</tt> may be constructed using the
  163.52 + * {@link Collections#synchronizedMap Collections.synchronizedMap}
  163.53 + * method.
  163.54 + *
  163.55 + * <p> This class is intended primarily for use with key objects whose
  163.56 + * <tt>equals</tt> methods test for object identity using the
  163.57 + * <tt>==</tt> operator.  Once such a key is discarded it can never be
  163.58 + * recreated, so it is impossible to do a lookup of that key in a
  163.59 + * <tt>WeakHashMap</tt> at some later time and be surprised that its entry
  163.60 + * has been removed.  This class will work perfectly well with key objects
  163.61 + * whose <tt>equals</tt> methods are not based upon object identity, such
  163.62 + * as <tt>String</tt> instances.  With such recreatable key objects,
  163.63 + * however, the automatic removal of <tt>WeakHashMap</tt> entries whose
  163.64 + * keys have been discarded may prove to be confusing.
  163.65 + *
  163.66 + * <p> The behavior of the <tt>WeakHashMap</tt> class depends in part upon
  163.67 + * the actions of the garbage collector, so several familiar (though not
  163.68 + * required) <tt>Map</tt> invariants do not hold for this class.  Because
  163.69 + * the garbage collector may discard keys at any time, a
  163.70 + * <tt>WeakHashMap</tt> may behave as though an unknown thread is silently
  163.71 + * removing entries.  In particular, even if you synchronize on a
  163.72 + * <tt>WeakHashMap</tt> instance and invoke none of its mutator methods, it
  163.73 + * is possible for the <tt>size</tt> method to return smaller values over
  163.74 + * time, for the <tt>isEmpty</tt> method to return <tt>false</tt> and
  163.75 + * then <tt>true</tt>, for the <tt>containsKey</tt> method to return
  163.76 + * <tt>true</tt> and later <tt>false</tt> for a given key, for the
  163.77 + * <tt>get</tt> method to return a value for a given key but later return
  163.78 + * <tt>null</tt>, for the <tt>put</tt> method to return
  163.79 + * <tt>null</tt> and the <tt>remove</tt> method to return
  163.80 + * <tt>false</tt> for a key that previously appeared to be in the map, and
  163.81 + * for successive examinations of the key set, the value collection, and
  163.82 + * the entry set to yield successively smaller numbers of elements.
  163.83 + *
  163.84 + * <p> Each key object in a <tt>WeakHashMap</tt> is stored indirectly as
  163.85 + * the referent of a weak reference.  Therefore a key will automatically be
  163.86 + * removed only after the weak references to it, both inside and outside of the
  163.87 + * map, have been cleared by the garbage collector.
  163.88 + *
  163.89 + * <p> <strong>Implementation note:</strong> The value objects in a
  163.90 + * <tt>WeakHashMap</tt> are held by ordinary strong references.  Thus care
  163.91 + * should be taken to ensure that value objects do not strongly refer to their
  163.92 + * own keys, either directly or indirectly, since that will prevent the keys
  163.93 + * from being discarded.  Note that a value object may refer indirectly to its
  163.94 + * key via the <tt>WeakHashMap</tt> itself; that is, a value object may
  163.95 + * strongly refer to some other key object whose associated value object, in
  163.96 + * turn, strongly refers to the key of the first value object.  One way
  163.97 + * to deal with this is to wrap values themselves within
  163.98 + * <tt>WeakReferences</tt> before
  163.99 + * inserting, as in: <tt>m.put(key, new WeakReference(value))</tt>,
 163.100 + * and then unwrapping upon each <tt>get</tt>.
 163.101 + *
 163.102 + * <p>The iterators returned by the <tt>iterator</tt> method of the collections
 163.103 + * returned by all of this class's "collection view methods" are
 163.104 + * <i>fail-fast</i>: if the map is structurally modified at any time after the
 163.105 + * iterator is created, in any way except through the iterator's own
 163.106 + * <tt>remove</tt> method, the iterator will throw a {@link
 163.107 + * ConcurrentModificationException}.  Thus, in the face of concurrent
 163.108 + * modification, the iterator fails quickly and cleanly, rather than risking
 163.109 + * arbitrary, non-deterministic behavior at an undetermined time in the future.
 163.110 + *
 163.111 + * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
 163.112 + * as it is, generally speaking, impossible to make any hard guarantees in the
 163.113 + * presence of unsynchronized concurrent modification.  Fail-fast iterators
 163.114 + * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
 163.115 + * Therefore, it would be wrong to write a program that depended on this
 163.116 + * exception for its correctness:  <i>the fail-fast behavior of iterators
 163.117 + * should be used only to detect bugs.</i>
 163.118 + *
 163.119 + * <p>This class is a member of the
 163.120 + * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 163.121 + * Java Collections Framework</a>.
 163.122 + *
 163.123 + * @param <K> the type of keys maintained by this map
 163.124 + * @param <V> the type of mapped values
 163.125 + *
 163.126 + * @author      Doug Lea
 163.127 + * @author      Josh Bloch
 163.128 + * @author      Mark Reinhold
 163.129 + * @since       1.2
 163.130 + * @see         java.util.HashMap
 163.131 + * @see         java.lang.ref.WeakReference
 163.132 + */
 163.133 +public class WeakHashMap<K,V>
 163.134 +    extends AbstractMap<K,V>
 163.135 +    implements Map<K,V> {
 163.136 +
 163.137 +    /**
 163.138 +     * The default initial capacity -- MUST be a power of two.
 163.139 +     */
 163.140 +    private static final int DEFAULT_INITIAL_CAPACITY = 16;
 163.141 +
 163.142 +    /**
 163.143 +     * The maximum capacity, used if a higher value is implicitly specified
 163.144 +     * by either of the constructors with arguments.
 163.145 +     * MUST be a power of two <= 1<<30.
 163.146 +     */
 163.147 +    private static final int MAXIMUM_CAPACITY = 1 << 30;
 163.148 +
 163.149 +    /**
 163.150 +     * The load factor used when none specified in constructor.
 163.151 +     */
 163.152 +    private static final float DEFAULT_LOAD_FACTOR = 0.75f;
 163.153 +
 163.154 +    /**
 163.155 +     * The table, resized as necessary. Length MUST Always be a power of two.
 163.156 +     */
 163.157 +    Entry<K,V>[] table;
 163.158 +
 163.159 +    /**
 163.160 +     * The number of key-value mappings contained in this weak hash map.
 163.161 +     */
 163.162 +    private int size;
 163.163 +
 163.164 +    /**
 163.165 +     * The next size value at which to resize (capacity * load factor).
 163.166 +     */
 163.167 +    private int threshold;
 163.168 +
 163.169 +    /**
 163.170 +     * The load factor for the hash table.
 163.171 +     */
 163.172 +    private final float loadFactor;
 163.173 +
 163.174 +    /**
 163.175 +     * Reference queue for cleared WeakEntries
 163.176 +     */
 163.177 +    private final ReferenceQueue<Object> queue = new ReferenceQueue<>();
 163.178 +
 163.179 +    /**
 163.180 +     * The number of times this WeakHashMap has been structurally modified.
 163.181 +     * Structural modifications are those that change the number of
 163.182 +     * mappings in the map or otherwise modify its internal structure
 163.183 +     * (e.g., rehash).  This field is used to make iterators on
 163.184 +     * Collection-views of the map fail-fast.
 163.185 +     *
 163.186 +     * @see ConcurrentModificationException
 163.187 +     */
 163.188 +    int modCount;
 163.189 +
 163.190 +    @SuppressWarnings("unchecked")
 163.191 +    private Entry<K,V>[] newTable(int n) {
 163.192 +        return (Entry<K,V>[]) new Entry[n];
 163.193 +    }
 163.194 +
 163.195 +    /**
 163.196 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
 163.197 +     * capacity and the given load factor.
 163.198 +     *
 163.199 +     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
 163.200 +     * @param  loadFactor      The load factor of the <tt>WeakHashMap</tt>
 163.201 +     * @throws IllegalArgumentException if the initial capacity is negative,
 163.202 +     *         or if the load factor is nonpositive.
 163.203 +     */
 163.204 +    public WeakHashMap(int initialCapacity, float loadFactor) {
 163.205 +        if (initialCapacity < 0)
 163.206 +            throw new IllegalArgumentException("Illegal Initial Capacity: "+
 163.207 +                                               initialCapacity);
 163.208 +        if (initialCapacity > MAXIMUM_CAPACITY)
 163.209 +            initialCapacity = MAXIMUM_CAPACITY;
 163.210 +
 163.211 +        if (loadFactor <= 0 || Float.isNaN(loadFactor))
 163.212 +            throw new IllegalArgumentException("Illegal Load factor: "+
 163.213 +                                               loadFactor);
 163.214 +        int capacity = 1;
 163.215 +        while (capacity < initialCapacity)
 163.216 +            capacity <<= 1;
 163.217 +        table = newTable(capacity);
 163.218 +        this.loadFactor = loadFactor;
 163.219 +        threshold = (int)(capacity * loadFactor);
 163.220 +    }
 163.221 +
 163.222 +    /**
 163.223 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the given initial
 163.224 +     * capacity and the default load factor (0.75).
 163.225 +     *
 163.226 +     * @param  initialCapacity The initial capacity of the <tt>WeakHashMap</tt>
 163.227 +     * @throws IllegalArgumentException if the initial capacity is negative
 163.228 +     */
 163.229 +    public WeakHashMap(int initialCapacity) {
 163.230 +        this(initialCapacity, DEFAULT_LOAD_FACTOR);
 163.231 +    }
 163.232 +
 163.233 +    /**
 163.234 +     * Constructs a new, empty <tt>WeakHashMap</tt> with the default initial
 163.235 +     * capacity (16) and load factor (0.75).
 163.236 +     */
 163.237 +    public WeakHashMap() {
 163.238 +        this.loadFactor = DEFAULT_LOAD_FACTOR;
 163.239 +        threshold = DEFAULT_INITIAL_CAPACITY;
 163.240 +        table = newTable(DEFAULT_INITIAL_CAPACITY);
 163.241 +    }
 163.242 +
 163.243 +    /**
 163.244 +     * Constructs a new <tt>WeakHashMap</tt> with the same mappings as the
 163.245 +     * specified map.  The <tt>WeakHashMap</tt> is created with the default
 163.246 +     * load factor (0.75) and an initial capacity sufficient to hold the
 163.247 +     * mappings in the specified map.
 163.248 +     *
 163.249 +     * @param   m the map whose mappings are to be placed in this map
 163.250 +     * @throws  NullPointerException if the specified map is null
 163.251 +     * @since   1.3
 163.252 +     */
 163.253 +    public WeakHashMap(Map<? extends K, ? extends V> m) {
 163.254 +        this(Math.max((int) (m.size() / DEFAULT_LOAD_FACTOR) + 1, 16),
 163.255 +             DEFAULT_LOAD_FACTOR);
 163.256 +        putAll(m);
 163.257 +    }
 163.258 +
 163.259 +    // internal utilities
 163.260 +
 163.261 +    /**
 163.262 +     * Value representing null keys inside tables.
 163.263 +     */
 163.264 +    private static final Object NULL_KEY = new Object();
 163.265 +
 163.266 +    /**
 163.267 +     * Use NULL_KEY for key if it is null.
 163.268 +     */
 163.269 +    private static Object maskNull(Object key) {
 163.270 +        return (key == null) ? NULL_KEY : key;
 163.271 +    }
 163.272 +
 163.273 +    /**
 163.274 +     * Returns internal representation of null key back to caller as null.
 163.275 +     */
 163.276 +    static Object unmaskNull(Object key) {
 163.277 +        return (key == NULL_KEY) ? null : key;
 163.278 +    }
 163.279 +
 163.280 +    /**
 163.281 +     * Checks for equality of non-null reference x and possibly-null y.  By
 163.282 +     * default uses Object.equals.
 163.283 +     */
 163.284 +    private static boolean eq(Object x, Object y) {
 163.285 +        return x == y || x.equals(y);
 163.286 +    }
 163.287 +
 163.288 +    /**
 163.289 +     * Returns index for hash code h.
 163.290 +     */
 163.291 +    private static int indexFor(int h, int length) {
 163.292 +        return h & (length-1);
 163.293 +    }
 163.294 +
 163.295 +    /**
 163.296 +     * Expunges stale entries from the table.
 163.297 +     */
 163.298 +    private void expungeStaleEntries() {
 163.299 +        for (Object x; (x = queue.poll()) != null; ) {
 163.300 +            synchronized (queue) {
 163.301 +                @SuppressWarnings("unchecked")
 163.302 +                    Entry<K,V> e = (Entry<K,V>) x;
 163.303 +                int i = indexFor(e.hash, table.length);
 163.304 +
 163.305 +                Entry<K,V> prev = table[i];
 163.306 +                Entry<K,V> p = prev;
 163.307 +                while (p != null) {
 163.308 +                    Entry<K,V> next = p.next;
 163.309 +                    if (p == e) {
 163.310 +                        if (prev == e)
 163.311 +                            table[i] = next;
 163.312 +                        else
 163.313 +                            prev.next = next;
 163.314 +                        // Must not null out e.next;
 163.315 +                        // stale entries may be in use by a HashIterator
 163.316 +                        e.value = null; // Help GC
 163.317 +                        size--;
 163.318 +                        break;
 163.319 +                    }
 163.320 +                    prev = p;
 163.321 +                    p = next;
 163.322 +                }
 163.323 +            }
 163.324 +        }
 163.325 +    }
 163.326 +
 163.327 +    /**
 163.328 +     * Returns the table after first expunging stale entries.
 163.329 +     */
 163.330 +    private Entry<K,V>[] getTable() {
 163.331 +        expungeStaleEntries();
 163.332 +        return table;
 163.333 +    }
 163.334 +
 163.335 +    /**
 163.336 +     * Returns the number of key-value mappings in this map.
 163.337 +     * This result is a snapshot, and may not reflect unprocessed
 163.338 +     * entries that will be removed before next attempted access
 163.339 +     * because they are no longer referenced.
 163.340 +     */
 163.341 +    public int size() {
 163.342 +        if (size == 0)
 163.343 +            return 0;
 163.344 +        expungeStaleEntries();
 163.345 +        return size;
 163.346 +    }
 163.347 +
 163.348 +    /**
 163.349 +     * Returns <tt>true</tt> if this map contains no key-value mappings.
 163.350 +     * This result is a snapshot, and may not reflect unprocessed
 163.351 +     * entries that will be removed before next attempted access
 163.352 +     * because they are no longer referenced.
 163.353 +     */
 163.354 +    public boolean isEmpty() {
 163.355 +        return size() == 0;
 163.356 +    }
 163.357 +
 163.358 +    /**
 163.359 +     * Returns the value to which the specified key is mapped,
 163.360 +     * or {@code null} if this map contains no mapping for the key.
 163.361 +     *
 163.362 +     * <p>More formally, if this map contains a mapping from a key
 163.363 +     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
 163.364 +     * key.equals(k))}, then this method returns {@code v}; otherwise
 163.365 +     * it returns {@code null}.  (There can be at most one such mapping.)
 163.366 +     *
 163.367 +     * <p>A return value of {@code null} does not <i>necessarily</i>
 163.368 +     * indicate that the map contains no mapping for the key; it's also
 163.369 +     * possible that the map explicitly maps the key to {@code null}.
 163.370 +     * The {@link #containsKey containsKey} operation may be used to
 163.371 +     * distinguish these two cases.
 163.372 +     *
 163.373 +     * @see #put(Object, Object)
 163.374 +     */
 163.375 +    public V get(Object key) {
 163.376 +        Object k = maskNull(key);
 163.377 +        int h = HashMap.hash(k.hashCode());
 163.378 +        Entry<K,V>[] tab = getTable();
 163.379 +        int index = indexFor(h, tab.length);
 163.380 +        Entry<K,V> e = tab[index];
 163.381 +        while (e != null) {
 163.382 +            if (e.hash == h && eq(k, e.get()))
 163.383 +                return e.value;
 163.384 +            e = e.next;
 163.385 +        }
 163.386 +        return null;
 163.387 +    }
 163.388 +
 163.389 +    /**
 163.390 +     * Returns <tt>true</tt> if this map contains a mapping for the
 163.391 +     * specified key.
 163.392 +     *
 163.393 +     * @param  key   The key whose presence in this map is to be tested
 163.394 +     * @return <tt>true</tt> if there is a mapping for <tt>key</tt>;
 163.395 +     *         <tt>false</tt> otherwise
 163.396 +     */
 163.397 +    public boolean containsKey(Object key) {
 163.398 +        return getEntry(key) != null;
 163.399 +    }
 163.400 +
 163.401 +    /**
 163.402 +     * Returns the entry associated with the specified key in this map.
 163.403 +     * Returns null if the map contains no mapping for this key.
 163.404 +     */
 163.405 +    Entry<K,V> getEntry(Object key) {
 163.406 +        Object k = maskNull(key);
 163.407 +        int h = HashMap.hash(k.hashCode());
 163.408 +        Entry<K,V>[] tab = getTable();
 163.409 +        int index = indexFor(h, tab.length);
 163.410 +        Entry<K,V> e = tab[index];
 163.411 +        while (e != null && !(e.hash == h && eq(k, e.get())))
 163.412 +            e = e.next;
 163.413 +        return e;
 163.414 +    }
 163.415 +
 163.416 +    /**
 163.417 +     * Associates the specified value with the specified key in this map.
 163.418 +     * If the map previously contained a mapping for this key, the old
 163.419 +     * value is replaced.
 163.420 +     *
 163.421 +     * @param key key with which the specified value is to be associated.
 163.422 +     * @param value value to be associated with the specified key.
 163.423 +     * @return the previous value associated with <tt>key</tt>, or
 163.424 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
 163.425 +     *         (A <tt>null</tt> return can also indicate that the map
 163.426 +     *         previously associated <tt>null</tt> with <tt>key</tt>.)
 163.427 +     */
 163.428 +    public V put(K key, V value) {
 163.429 +        Object k = maskNull(key);
 163.430 +        int h = HashMap.hash(k.hashCode());
 163.431 +        Entry<K,V>[] tab = getTable();
 163.432 +        int i = indexFor(h, tab.length);
 163.433 +
 163.434 +        for (Entry<K,V> e = tab[i]; e != null; e = e.next) {
 163.435 +            if (h == e.hash && eq(k, e.get())) {
 163.436 +                V oldValue = e.value;
 163.437 +                if (value != oldValue)
 163.438 +                    e.value = value;
 163.439 +                return oldValue;
 163.440 +            }
 163.441 +        }
 163.442 +
 163.443 +        modCount++;
 163.444 +        Entry<K,V> e = tab[i];
 163.445 +        tab[i] = new Entry<>(k, value, queue, h, e);
 163.446 +        if (++size >= threshold)
 163.447 +            resize(tab.length * 2);
 163.448 +        return null;
 163.449 +    }
 163.450 +
 163.451 +    /**
 163.452 +     * Rehashes the contents of this map into a new array with a
 163.453 +     * larger capacity.  This method is called automatically when the
 163.454 +     * number of keys in this map reaches its threshold.
 163.455 +     *
 163.456 +     * If current capacity is MAXIMUM_CAPACITY, this method does not
 163.457 +     * resize the map, but sets threshold to Integer.MAX_VALUE.
 163.458 +     * This has the effect of preventing future calls.
 163.459 +     *
 163.460 +     * @param newCapacity the new capacity, MUST be a power of two;
 163.461 +     *        must be greater than current capacity unless current
 163.462 +     *        capacity is MAXIMUM_CAPACITY (in which case value
 163.463 +     *        is irrelevant).
 163.464 +     */
 163.465 +    void resize(int newCapacity) {
 163.466 +        Entry<K,V>[] oldTable = getTable();
 163.467 +        int oldCapacity = oldTable.length;
 163.468 +        if (oldCapacity == MAXIMUM_CAPACITY) {
 163.469 +            threshold = Integer.MAX_VALUE;
 163.470 +            return;
 163.471 +        }
 163.472 +
 163.473 +        Entry<K,V>[] newTable = newTable(newCapacity);
 163.474 +        transfer(oldTable, newTable);
 163.475 +        table = newTable;
 163.476 +
 163.477 +        /*
 163.478 +         * If ignoring null elements and processing ref queue caused massive
 163.479 +         * shrinkage, then restore old table.  This should be rare, but avoids
 163.480 +         * unbounded expansion of garbage-filled tables.
 163.481 +         */
 163.482 +        if (size >= threshold / 2) {
 163.483 +            threshold = (int)(newCapacity * loadFactor);
 163.484 +        } else {
 163.485 +            expungeStaleEntries();
 163.486 +            transfer(newTable, oldTable);
 163.487 +            table = oldTable;
 163.488 +        }
 163.489 +    }
 163.490 +
 163.491 +    /** Transfers all entries from src to dest tables */
 163.492 +    private void transfer(Entry<K,V>[] src, Entry<K,V>[] dest) {
 163.493 +        for (int j = 0; j < src.length; ++j) {
 163.494 +            Entry<K,V> e = src[j];
 163.495 +            src[j] = null;
 163.496 +            while (e != null) {
 163.497 +                Entry<K,V> next = e.next;
 163.498 +                Object key = e.get();
 163.499 +                if (key == null) {
 163.500 +                    e.next = null;  // Help GC
 163.501 +                    e.value = null; //  "   "
 163.502 +                    size--;
 163.503 +                } else {
 163.504 +                    int i = indexFor(e.hash, dest.length);
 163.505 +                    e.next = dest[i];
 163.506 +                    dest[i] = e;
 163.507 +                }
 163.508 +                e = next;
 163.509 +            }
 163.510 +        }
 163.511 +    }
 163.512 +
 163.513 +    /**
 163.514 +     * Copies all of the mappings from the specified map to this map.
 163.515 +     * These mappings will replace any mappings that this map had for any
 163.516 +     * of the keys currently in the specified map.
 163.517 +     *
 163.518 +     * @param m mappings to be stored in this map.
 163.519 +     * @throws  NullPointerException if the specified map is null.
 163.520 +     */
 163.521 +    public void putAll(Map<? extends K, ? extends V> m) {
 163.522 +        int numKeysToBeAdded = m.size();
 163.523 +        if (numKeysToBeAdded == 0)
 163.524 +            return;
 163.525 +
 163.526 +        /*
 163.527 +         * Expand the map if the map if the number of mappings to be added
 163.528 +         * is greater than or equal to threshold.  This is conservative; the
 163.529 +         * obvious condition is (m.size() + size) >= threshold, but this
 163.530 +         * condition could result in a map with twice the appropriate capacity,
 163.531 +         * if the keys to be added overlap with the keys already in this map.
 163.532 +         * By using the conservative calculation, we subject ourself
 163.533 +         * to at most one extra resize.
 163.534 +         */
 163.535 +        if (numKeysToBeAdded > threshold) {
 163.536 +            int targetCapacity = (int)(numKeysToBeAdded / loadFactor + 1);
 163.537 +            if (targetCapacity > MAXIMUM_CAPACITY)
 163.538 +                targetCapacity = MAXIMUM_CAPACITY;
 163.539 +            int newCapacity = table.length;
 163.540 +            while (newCapacity < targetCapacity)
 163.541 +                newCapacity <<= 1;
 163.542 +            if (newCapacity > table.length)
 163.543 +                resize(newCapacity);
 163.544 +        }
 163.545 +
 163.546 +        for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
 163.547 +            put(e.getKey(), e.getValue());
 163.548 +    }
 163.549 +
 163.550 +    /**
 163.551 +     * Removes the mapping for a key from this weak hash map if it is present.
 163.552 +     * More formally, if this map contains a mapping from key <tt>k</tt> to
 163.553 +     * value <tt>v</tt> such that <code>(key==null ?  k==null :
 163.554 +     * key.equals(k))</code>, that mapping is removed.  (The map can contain
 163.555 +     * at most one such mapping.)
 163.556 +     *
 163.557 +     * <p>Returns the value to which this map previously associated the key,
 163.558 +     * or <tt>null</tt> if the map contained no mapping for the key.  A
 163.559 +     * return value of <tt>null</tt> does not <i>necessarily</i> indicate
 163.560 +     * that the map contained no mapping for the key; it's also possible
 163.561 +     * that the map explicitly mapped the key to <tt>null</tt>.
 163.562 +     *
 163.563 +     * <p>The map will not contain a mapping for the specified key once the
 163.564 +     * call returns.
 163.565 +     *
 163.566 +     * @param key key whose mapping is to be removed from the map
 163.567 +     * @return the previous value associated with <tt>key</tt>, or
 163.568 +     *         <tt>null</tt> if there was no mapping for <tt>key</tt>
 163.569 +     */
 163.570 +    public V remove(Object key) {
 163.571 +        Object k = maskNull(key);
 163.572 +        int h = HashMap.hash(k.hashCode());
 163.573 +        Entry<K,V>[] tab = getTable();
 163.574 +        int i = indexFor(h, tab.length);
 163.575 +        Entry<K,V> prev = tab[i];
 163.576 +        Entry<K,V> e = prev;
 163.577 +
 163.578 +        while (e != null) {
 163.579 +            Entry<K,V> next = e.next;
 163.580 +            if (h == e.hash && eq(k, e.get())) {
 163.581 +                modCount++;
 163.582 +                size--;
 163.583 +                if (prev == e)
 163.584 +                    tab[i] = next;
 163.585 +                else
 163.586 +                    prev.next = next;
 163.587 +                return e.value;
 163.588 +            }
 163.589 +            prev = e;
 163.590 +            e = next;
 163.591 +        }
 163.592 +
 163.593 +        return null;
 163.594 +    }
 163.595 +
 163.596 +    /** Special version of remove needed by Entry set */
 163.597 +    boolean removeMapping(Object o) {
 163.598 +        if (!(o instanceof Map.Entry))
 163.599 +            return false;
 163.600 +        Entry<K,V>[] tab = getTable();
 163.601 +        Map.Entry<?,?> entry = (Map.Entry<?,?>)o;
 163.602 +        Object k = maskNull(entry.getKey());
 163.603 +        int h = HashMap.hash(k.hashCode());
 163.604 +        int i = indexFor(h, tab.length);
 163.605 +        Entry<K,V> prev = tab[i];
 163.606 +        Entry<K,V> e = prev;
 163.607 +
 163.608 +        while (e != null) {
 163.609 +            Entry<K,V> next = e.next;
 163.610 +            if (h == e.hash && e.equals(entry)) {
 163.611 +                modCount++;
 163.612 +                size--;
 163.613 +                if (prev == e)
 163.614 +                    tab[i] = next;
 163.615 +                else
 163.616 +                    prev.next = next;
 163.617 +                return true;
 163.618 +            }
 163.619 +            prev = e;
 163.620 +            e = next;
 163.621 +        }
 163.622 +
 163.623 +        return false;
 163.624 +    }
 163.625 +
 163.626 +    /**
 163.627 +     * Removes all of the mappings from this map.
 163.628 +     * The map will be empty after this call returns.
 163.629 +     */
 163.630 +    public void clear() {
 163.631 +        // clear out ref queue. We don't need to expunge entries
 163.632 +        // since table is getting cleared.
 163.633 +        while (queue.poll() != null)
 163.634 +            ;
 163.635 +
 163.636 +        modCount++;
 163.637 +        Arrays.fill(table, null);
 163.638 +        size = 0;
 163.639 +
 163.640 +        // Allocation of array may have caused GC, which may have caused
 163.641 +        // additional entries to go stale.  Removing these entries from the
 163.642 +        // reference queue will make them eligible for reclamation.
 163.643 +        while (queue.poll() != null)
 163.644 +            ;
 163.645 +    }
 163.646 +
 163.647 +    /**
 163.648 +     * Returns <tt>true</tt> if this map maps one or more keys to the
 163.649 +     * specified value.
 163.650 +     *
 163.651 +     * @param value value whose presence in this map is to be tested
 163.652 +     * @return <tt>true</tt> if this map maps one or more keys to the
 163.653 +     *         specified value
 163.654 +     */
 163.655 +    public boolean containsValue(Object value) {
 163.656 +        if (value==null)
 163.657 +            return containsNullValue();
 163.658 +
 163.659 +        Entry<K,V>[] tab = getTable();
 163.660 +        for (int i = tab.length; i-- > 0;)
 163.661 +            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
 163.662 +                if (value.equals(e.value))
 163.663 +                    return true;
 163.664 +        return false;
 163.665 +    }
 163.666 +
 163.667 +    /**
 163.668 +     * Special-case code for containsValue with null argument
 163.669 +     */
 163.670 +    private boolean containsNullValue() {
 163.671 +        Entry<K,V>[] tab = getTable();
 163.672 +        for (int i = tab.length; i-- > 0;)
 163.673 +            for (Entry<K,V> e = tab[i]; e != null; e = e.next)
 163.674 +                if (e.value==null)
 163.675 +                    return true;
 163.676 +        return false;
 163.677 +    }
 163.678 +
 163.679 +    /**
 163.680 +     * The entries in this hash table extend WeakReference, using its main ref
 163.681 +     * field as the key.
 163.682 +     */
 163.683 +    private static class Entry<K,V> extends WeakReference<Object> implements Map.Entry<K,V> {
 163.684 +        V value;
 163.685 +        final int hash;
 163.686 +        Entry<K,V> next;
 163.687 +
 163.688 +        /**
 163.689 +         * Creates new entry.
 163.690 +         */
 163.691 +        Entry(Object key, V value,
 163.692 +              ReferenceQueue<Object> queue,
 163.693 +              int hash, Entry<K,V> next) {
 163.694 +            super(key, queue);
 163.695 +            this.value = value;
 163.696 +            this.hash  = hash;
 163.697 +            this.next  = next;
 163.698 +        }
 163.699 +
 163.700 +        @SuppressWarnings("unchecked")
 163.701 +        public K getKey() {
 163.702 +            return (K) WeakHashMap.unmaskNull(get());
 163.703 +        }
 163.704 +
 163.705 +        public V getValue() {
 163.706 +            return value;
 163.707 +        }
 163.708 +
 163.709 +        public V setValue(V newValue) {
 163.710 +            V oldValue = value;
 163.711 +            value = newValue;
 163.712 +            return oldValue;
 163.713 +        }
 163.714 +
 163.715 +        public boolean equals(Object o) {
 163.716 +            if (!(o instanceof Map.Entry))
 163.717 +                return false;
 163.718 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
 163.719 +            K k1 = getKey();
 163.720 +            Object k2 = e.getKey();
 163.721 +            if (k1 == k2 || (k1 != null && k1.equals(k2))) {
 163.722 +                V v1 = getValue();
 163.723 +                Object v2 = e.getValue();
 163.724 +                if (v1 == v2 || (v1 != null && v1.equals(v2)))
 163.725 +                    return true;
 163.726 +            }
 163.727 +            return false;
 163.728 +        }
 163.729 +
 163.730 +        public int hashCode() {
 163.731 +            K k = getKey();
 163.732 +            V v = getValue();
 163.733 +            return ((k==null ? 0 : k.hashCode()) ^
 163.734 +                    (v==null ? 0 : v.hashCode()));
 163.735 +        }
 163.736 +
 163.737 +        public String toString() {
 163.738 +            return getKey() + "=" + getValue();
 163.739 +        }
 163.740 +    }
 163.741 +
 163.742 +    private abstract class HashIterator<T> implements Iterator<T> {
 163.743 +        private int index;
 163.744 +        private Entry<K,V> entry = null;
 163.745 +        private Entry<K,V> lastReturned = null;
 163.746 +        private int expectedModCount = modCount;
 163.747 +
 163.748 +        /**
 163.749 +         * Strong reference needed to avoid disappearance of key
 163.750 +         * between hasNext and next
 163.751 +         */
 163.752 +        private Object nextKey = null;
 163.753 +
 163.754 +        /**
 163.755 +         * Strong reference needed to avoid disappearance of key
 163.756 +         * between nextEntry() and any use of the entry
 163.757 +         */
 163.758 +        private Object currentKey = null;
 163.759 +
 163.760 +        HashIterator() {
 163.761 +            index = isEmpty() ? 0 : table.length;
 163.762 +        }
 163.763 +
 163.764 +        public boolean hasNext() {
 163.765 +            Entry<K,V>[] t = table;
 163.766 +
 163.767 +            while (nextKey == null) {
 163.768 +                Entry<K,V> e = entry;
 163.769 +                int i = index;
 163.770 +                while (e == null && i > 0)
 163.771 +                    e = t[--i];
 163.772 +                entry = e;
 163.773 +                index = i;
 163.774 +                if (e == null) {
 163.775 +                    currentKey = null;
 163.776 +                    return false;
 163.777 +                }
 163.778 +                nextKey = e.get(); // hold on to key in strong ref
 163.779 +                if (nextKey == null)
 163.780 +                    entry = entry.next;
 163.781 +            }
 163.782 +            return true;
 163.783 +        }
 163.784 +
 163.785 +        /** The common parts of next() across different types of iterators */
 163.786 +        protected Entry<K,V> nextEntry() {
 163.787 +            if (modCount != expectedModCount)
 163.788 +                throw new ConcurrentModificationException();
 163.789 +            if (nextKey == null && !hasNext())
 163.790 +                throw new NoSuchElementException();
 163.791 +
 163.792 +            lastReturned = entry;
 163.793 +            entry = entry.next;
 163.794 +            currentKey = nextKey;
 163.795 +            nextKey = null;
 163.796 +            return lastReturned;
 163.797 +        }
 163.798 +
 163.799 +        public void remove() {
 163.800 +            if (lastReturned == null)
 163.801 +                throw new IllegalStateException();
 163.802 +            if (modCount != expectedModCount)
 163.803 +                throw new ConcurrentModificationException();
 163.804 +
 163.805 +            WeakHashMap.this.remove(currentKey);
 163.806 +            expectedModCount = modCount;
 163.807 +            lastReturned = null;
 163.808 +            currentKey = null;
 163.809 +        }
 163.810 +
 163.811 +    }
 163.812 +
 163.813 +    private class ValueIterator extends HashIterator<V> {
 163.814 +        public V next() {
 163.815 +            return nextEntry().value;
 163.816 +        }
 163.817 +    }
 163.818 +
 163.819 +    private class KeyIterator extends HashIterator<K> {
 163.820 +        public K next() {
 163.821 +            return nextEntry().getKey();
 163.822 +        }
 163.823 +    }
 163.824 +
 163.825 +    private class EntryIterator extends HashIterator<Map.Entry<K,V>> {
 163.826 +        public Map.Entry<K,V> next() {
 163.827 +            return nextEntry();
 163.828 +        }
 163.829 +    }
 163.830 +
 163.831 +    // Views
 163.832 +
 163.833 +    private transient Set<Map.Entry<K,V>> entrySet = null;
 163.834 +
 163.835 +    /**
 163.836 +     * Returns a {@link Set} view of the keys contained in this map.
 163.837 +     * The set is backed by the map, so changes to the map are
 163.838 +     * reflected in the set, and vice-versa.  If the map is modified
 163.839 +     * while an iteration over the set is in progress (except through
 163.840 +     * the iterator's own <tt>remove</tt> operation), the results of
 163.841 +     * the iteration are undefined.  The set supports element removal,
 163.842 +     * which removes the corresponding mapping from the map, via the
 163.843 +     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
 163.844 +     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
 163.845 +     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
 163.846 +     * operations.
 163.847 +     */
 163.848 +    public Set<K> keySet() {
 163.849 +        Set<K> ks = keySet;
 163.850 +        return (ks != null ? ks : (keySet = new KeySet()));
 163.851 +    }
 163.852 +
 163.853 +    private class KeySet extends AbstractSet<K> {
 163.854 +        public Iterator<K> iterator() {
 163.855 +            return new KeyIterator();
 163.856 +        }
 163.857 +
 163.858 +        public int size() {
 163.859 +            return WeakHashMap.this.size();
 163.860 +        }
 163.861 +
 163.862 +        public boolean contains(Object o) {
 163.863 +            return containsKey(o);
 163.864 +        }
 163.865 +
 163.866 +        public boolean remove(Object o) {
 163.867 +            if (containsKey(o)) {
 163.868 +                WeakHashMap.this.remove(o);
 163.869 +                return true;
 163.870 +            }
 163.871 +            else
 163.872 +                return false;
 163.873 +        }
 163.874 +
 163.875 +        public void clear() {
 163.876 +            WeakHashMap.this.clear();
 163.877 +        }
 163.878 +    }
 163.879 +
 163.880 +    /**
 163.881 +     * Returns a {@link Collection} view of the values contained in this map.
 163.882 +     * The collection is backed by the map, so changes to the map are
 163.883 +     * reflected in the collection, and vice-versa.  If the map is
 163.884 +     * modified while an iteration over the collection is in progress
 163.885 +     * (except through the iterator's own <tt>remove</tt> operation),
 163.886 +     * the results of the iteration are undefined.  The collection
 163.887 +     * supports element removal, which removes the corresponding
 163.888 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
 163.889 +     * <tt>Collection.remove</tt>, <tt>removeAll</tt>,
 163.890 +     * <tt>retainAll</tt> and <tt>clear</tt> operations.  It does not
 163.891 +     * support the <tt>add</tt> or <tt>addAll</tt> operations.
 163.892 +     */
 163.893 +    public Collection<V> values() {
 163.894 +        Collection<V> vs = values;
 163.895 +        return (vs != null) ? vs : (values = new Values());
 163.896 +    }
 163.897 +
 163.898 +    private class Values extends AbstractCollection<V> {
 163.899 +        public Iterator<V> iterator() {
 163.900 +            return new ValueIterator();
 163.901 +        }
 163.902 +
 163.903 +        public int size() {
 163.904 +            return WeakHashMap.this.size();
 163.905 +        }
 163.906 +
 163.907 +        public boolean contains(Object o) {
 163.908 +            return containsValue(o);
 163.909 +        }
 163.910 +
 163.911 +        public void clear() {
 163.912 +            WeakHashMap.this.clear();
 163.913 +        }
 163.914 +    }
 163.915 +
 163.916 +    /**
 163.917 +     * Returns a {@link Set} view of the mappings contained in this map.
 163.918 +     * The set is backed by the map, so changes to the map are
 163.919 +     * reflected in the set, and vice-versa.  If the map is modified
 163.920 +     * while an iteration over the set is in progress (except through
 163.921 +     * the iterator's own <tt>remove</tt> operation, or through the
 163.922 +     * <tt>setValue</tt> operation on a map entry returned by the
 163.923 +     * iterator) the results of the iteration are undefined.  The set
 163.924 +     * supports element removal, which removes the corresponding
 163.925 +     * mapping from the map, via the <tt>Iterator.remove</tt>,
 163.926 +     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
 163.927 +     * <tt>clear</tt> operations.  It does not support the
 163.928 +     * <tt>add</tt> or <tt>addAll</tt> operations.
 163.929 +     */
 163.930 +    public Set<Map.Entry<K,V>> entrySet() {
 163.931 +        Set<Map.Entry<K,V>> es = entrySet;
 163.932 +        return es != null ? es : (entrySet = new EntrySet());
 163.933 +    }
 163.934 +
 163.935 +    private class EntrySet extends AbstractSet<Map.Entry<K,V>> {
 163.936 +        public Iterator<Map.Entry<K,V>> iterator() {
 163.937 +            return new EntryIterator();
 163.938 +        }
 163.939 +
 163.940 +        public boolean contains(Object o) {
 163.941 +            if (!(o instanceof Map.Entry))
 163.942 +                return false;
 163.943 +            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
 163.944 +            Entry<K,V> candidate = getEntry(e.getKey());
 163.945 +            return candidate != null && candidate.equals(e);
 163.946 +        }
 163.947 +
 163.948 +        public boolean remove(Object o) {
 163.949 +            return removeMapping(o);
 163.950 +        }
 163.951 +
 163.952 +        public int size() {
 163.953 +            return WeakHashMap.this.size();
 163.954 +        }
 163.955 +
 163.956 +        public void clear() {
 163.957 +            WeakHashMap.this.clear();
 163.958 +        }
 163.959 +
 163.960 +        private List<Map.Entry<K,V>> deepCopy() {
 163.961 +            List<Map.Entry<K,V>> list = new ArrayList<>(size());
 163.962 +            for (Map.Entry<K,V> e : this)
 163.963 +                list.add(new AbstractMap.SimpleEntry<>(e));
 163.964 +            return list;
 163.965 +        }
 163.966 +
 163.967 +        public Object[] toArray() {
 163.968 +            return deepCopy().toArray();
 163.969 +        }
 163.970 +
 163.971 +        public <T> T[] toArray(T[] a) {
 163.972 +            return deepCopy().toArray(a);
 163.973 +        }
 163.974 +    }
 163.975 +}
   164.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   164.2 +++ b/rt/emul/compact/src/main/java/java/util/concurrent/Executor.java	Mon Oct 07 14:20:58 2013 +0200
   164.3 @@ -0,0 +1,141 @@
   164.4 +/*
   164.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   164.6 + *
   164.7 + * This code is free software; you can redistribute it and/or modify it
   164.8 + * under the terms of the GNU General Public License version 2 only, as
   164.9 + * published by the Free Software Foundation.  Oracle designates this
  164.10 + * particular file as subject to the "Classpath" exception as provided
  164.11 + * by Oracle in the LICENSE file that accompanied this code.
  164.12 + *
  164.13 + * This code is distributed in the hope that it will be useful, but WITHOUT
  164.14 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  164.15 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  164.16 + * version 2 for more details (a copy is included in the LICENSE file that
  164.17 + * accompanied this code).
  164.18 + *
  164.19 + * You should have received a copy of the GNU General Public License version
  164.20 + * 2 along with this work; if not, write to the Free Software Foundation,
  164.21 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  164.22 + *
  164.23 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  164.24 + * or visit www.oracle.com if you need additional information or have any
  164.25 + * questions.
  164.26 + */
  164.27 +
  164.28 +/*
  164.29 + * This file is available under and governed by the GNU General Public
  164.30 + * License version 2 only, as published by the Free Software Foundation.
  164.31 + * However, the following notice accompanied the original version of this
  164.32 + * file:
  164.33 + *
  164.34 + * Written by Doug Lea with assistance from members of JCP JSR-166
  164.35 + * Expert Group and released to the public domain, as explained at
  164.36 + * http://creativecommons.org/publicdomain/zero/1.0/
  164.37 + */
  164.38 +
  164.39 +package java.util.concurrent;
  164.40 +
  164.41 +/**
  164.42 + * An object that executes submitted {@link Runnable} tasks. This
  164.43 + * interface provides a way of decoupling task submission from the
  164.44 + * mechanics of how each task will be run, including details of thread
  164.45 + * use, scheduling, etc.  An <tt>Executor</tt> is normally used
  164.46 + * instead of explicitly creating threads. For example, rather than
  164.47 + * invoking <tt>new Thread(new(RunnableTask())).start()</tt> for each
  164.48 + * of a set of tasks, you might use:
  164.49 + *
  164.50 + * <pre>
  164.51 + * Executor executor = <em>anExecutor</em>;
  164.52 + * executor.execute(new RunnableTask1());
  164.53 + * executor.execute(new RunnableTask2());
  164.54 + * ...
  164.55 + * </pre>
  164.56 + *
  164.57 + * However, the <tt>Executor</tt> interface does not strictly
  164.58 + * require that execution be asynchronous. In the simplest case, an
  164.59 + * executor can run the submitted task immediately in the caller's
  164.60 + * thread:
  164.61 + *
  164.62 + * <pre>
  164.63 + * class DirectExecutor implements Executor {
  164.64 + *     public void execute(Runnable r) {
  164.65 + *         r.run();
  164.66 + *     }
  164.67 + * }</pre>
  164.68 + *
  164.69 + * More typically, tasks are executed in some thread other
  164.70 + * than the caller's thread.  The executor below spawns a new thread
  164.71 + * for each task.
  164.72 + *
  164.73 + * <pre>
  164.74 + * class ThreadPerTaskExecutor implements Executor {
  164.75 + *     public void execute(Runnable r) {
  164.76 + *         new Thread(r).start();
  164.77 + *     }
  164.78 + * }</pre>
  164.79 + *
  164.80 + * Many <tt>Executor</tt> implementations impose some sort of
  164.81 + * limitation on how and when tasks are scheduled.  The executor below
  164.82 + * serializes the submission of tasks to a second executor,
  164.83 + * illustrating a composite executor.
  164.84 + *
  164.85 + *  <pre> {@code
  164.86 + * class SerialExecutor implements Executor {
  164.87 + *   final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
  164.88 + *   final Executor executor;
  164.89 + *   Runnable active;
  164.90 + *
  164.91 + *   SerialExecutor(Executor executor) {
  164.92 + *     this.executor = executor;
  164.93 + *   }
  164.94 + *
  164.95 + *   public synchronized void execute(final Runnable r) {
  164.96 + *     tasks.offer(new Runnable() {
  164.97 + *       public void run() {
  164.98 + *         try {
  164.99 + *           r.run();
 164.100 + *         } finally {
 164.101 + *           scheduleNext();
 164.102 + *         }
 164.103 + *       }
 164.104 + *     });
 164.105 + *     if (active == null) {
 164.106 + *       scheduleNext();
 164.107 + *     }
 164.108 + *   }
 164.109 + *
 164.110 + *   protected synchronized void scheduleNext() {
 164.111 + *     if ((active = tasks.poll()) != null) {
 164.112 + *       executor.execute(active);
 164.113 + *     }
 164.114 + *   }
 164.115 + * }}</pre>
 164.116 + *
 164.117 + * The <tt>Executor</tt> implementations provided in this package
 164.118 + * implement {@link ExecutorService}, which is a more extensive
 164.119 + * interface.  The {@link ThreadPoolExecutor} class provides an
 164.120 + * extensible thread pool implementation. The {@link Executors} class
 164.121 + * provides convenient factory methods for these Executors.
 164.122 + *
 164.123 + * <p>Memory consistency effects: Actions in a thread prior to
 164.124 + * submitting a {@code Runnable} object to an {@code Executor}
 164.125 + * <a href="package-summary.html#MemoryVisibility"><i>happen-before</i></a>
 164.126 + * its execution begins, perhaps in another thread.
 164.127 + *
 164.128 + * @since 1.5
 164.129 + * @author Doug Lea
 164.130 + */
 164.131 +public interface Executor {
 164.132 +
 164.133 +    /**
 164.134 +     * Executes the given command at some time in the future.  The command
 164.135 +     * may execute in a new thread, in a pooled thread, or in the calling
 164.136 +     * thread, at the discretion of the <tt>Executor</tt> implementation.
 164.137 +     *
 164.138 +     * @param command the runnable task
 164.139 +     * @throws RejectedExecutionException if this task cannot be
 164.140 +     * accepted for execution.
 164.141 +     * @throws NullPointerException if command is null
 164.142 +     */
 164.143 +    void execute(Runnable command);
 164.144 +}
   165.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   165.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/Level.java	Mon Oct 07 14:20:58 2013 +0200
   165.3 @@ -0,0 +1,372 @@
   165.4 +/*
   165.5 + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   165.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   165.7 + *
   165.8 + * This code is free software; you can redistribute it and/or modify it
   165.9 + * under the terms of the GNU General Public License version 2 only, as
  165.10 + * published by the Free Software Foundation.  Oracle designates this
  165.11 + * particular file as subject to the "Classpath" exception as provided
  165.12 + * by Oracle in the LICENSE file that accompanied this code.
  165.13 + *
  165.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  165.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  165.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  165.17 + * version 2 for more details (a copy is included in the LICENSE file that
  165.18 + * accompanied this code).
  165.19 + *
  165.20 + * You should have received a copy of the GNU General Public License version
  165.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  165.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  165.23 + *
  165.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  165.25 + * or visit www.oracle.com if you need additional information or have any
  165.26 + * questions.
  165.27 + */
  165.28 +
  165.29 +package java.util.logging;
  165.30 +
  165.31 +/**
  165.32 + * The Level class defines a set of standard logging levels that
  165.33 + * can be used to control logging output.  The logging Level objects
  165.34 + * are ordered and are specified by ordered integers.  Enabling logging
  165.35 + * at a given level also enables logging at all higher levels.
  165.36 + * <p>
  165.37 + * Clients should normally use the predefined Level constants such
  165.38 + * as Level.SEVERE.
  165.39 + * <p>
  165.40 + * The levels in descending order are:
  165.41 + * <ul>
  165.42 + * <li>SEVERE (highest value)
  165.43 + * <li>WARNING
  165.44 + * <li>INFO
  165.45 + * <li>CONFIG
  165.46 + * <li>FINE
  165.47 + * <li>FINER
  165.48 + * <li>FINEST  (lowest value)
  165.49 + * </ul>
  165.50 + * In addition there is a level OFF that can be used to turn
  165.51 + * off logging, and a level ALL that can be used to enable
  165.52 + * logging of all messages.
  165.53 + * <p>
  165.54 + * It is possible for third parties to define additional logging
  165.55 + * levels by subclassing Level.  In such cases subclasses should
  165.56 + * take care to chose unique integer level values and to ensure that
  165.57 + * they maintain the Object uniqueness property across serialization
  165.58 + * by defining a suitable readResolve method.
  165.59 + *
  165.60 + * @since 1.4
  165.61 + */
  165.62 +
  165.63 +public class Level implements java.io.Serializable {
  165.64 +    private static java.util.ArrayList<Level> known = new java.util.ArrayList<>();
  165.65 +    private static String defaultBundle = "sun.util.logging.resources.logging";
  165.66 +
  165.67 +    /**
  165.68 +     * @serial  The non-localized name of the level.
  165.69 +     */
  165.70 +    private final String name;
  165.71 +
  165.72 +    /**
  165.73 +     * @serial  The integer value of the level.
  165.74 +     */
  165.75 +    private final int value;
  165.76 +
  165.77 +    /**
  165.78 +     * @serial The resource bundle name to be used in localizing the level name.
  165.79 +     */
  165.80 +    private final String resourceBundleName;
  165.81 +
  165.82 +    /**
  165.83 +     * OFF is a special level that can be used to turn off logging.
  165.84 +     * This level is initialized to <CODE>Integer.MAX_VALUE</CODE>.
  165.85 +     */
  165.86 +    public static final Level OFF = new Level("OFF",Integer.MAX_VALUE, defaultBundle);
  165.87 +
  165.88 +    /**
  165.89 +     * SEVERE is a message level indicating a serious failure.
  165.90 +     * <p>
  165.91 +     * In general SEVERE messages should describe events that are
  165.92 +     * of considerable importance and which will prevent normal
  165.93 +     * program execution.   They should be reasonably intelligible
  165.94 +     * to end users and to system administrators.
  165.95 +     * This level is initialized to <CODE>1000</CODE>.
  165.96 +     */
  165.97 +    public static final Level SEVERE = new Level("SEVERE",1000, defaultBundle);
  165.98 +
  165.99 +    /**
 165.100 +     * WARNING is a message level indicating a potential problem.
 165.101 +     * <p>
 165.102 +     * In general WARNING messages should describe events that will
 165.103 +     * be of interest to end users or system managers, or which
 165.104 +     * indicate potential problems.
 165.105 +     * This level is initialized to <CODE>900</CODE>.
 165.106 +     */
 165.107 +    public static final Level WARNING = new Level("WARNING", 900, defaultBundle);
 165.108 +
 165.109 +    /**
 165.110 +     * INFO is a message level for informational messages.
 165.111 +     * <p>
 165.112 +     * Typically INFO messages will be written to the console
 165.113 +     * or its equivalent.  So the INFO level should only be
 165.114 +     * used for reasonably significant messages that will
 165.115 +     * make sense to end users and system administrators.
 165.116 +     * This level is initialized to <CODE>800</CODE>.
 165.117 +     */
 165.118 +    public static final Level INFO = new Level("INFO", 800, defaultBundle);
 165.119 +
 165.120 +    /**
 165.121 +     * CONFIG is a message level for static configuration messages.
 165.122 +     * <p>
 165.123 +     * CONFIG messages are intended to provide a variety of static
 165.124 +     * configuration information, to assist in debugging problems
 165.125 +     * that may be associated with particular configurations.
 165.126 +     * For example, CONFIG message might include the CPU type,
 165.127 +     * the graphics depth, the GUI look-and-feel, etc.
 165.128 +     * This level is initialized to <CODE>700</CODE>.
 165.129 +     */
 165.130 +    public static final Level CONFIG = new Level("CONFIG", 700, defaultBundle);
 165.131 +
 165.132 +    /**
 165.133 +     * FINE is a message level providing tracing information.
 165.134 +     * <p>
 165.135 +     * All of FINE, FINER, and FINEST are intended for relatively
 165.136 +     * detailed tracing.  The exact meaning of the three levels will
 165.137 +     * vary between subsystems, but in general, FINEST should be used
 165.138 +     * for the most voluminous detailed output, FINER for somewhat
 165.139 +     * less detailed output, and FINE for the  lowest volume (and
 165.140 +     * most important) messages.
 165.141 +     * <p>
 165.142 +     * In general the FINE level should be used for information
 165.143 +     * that will be broadly interesting to developers who do not have
 165.144 +     * a specialized interest in the specific subsystem.
 165.145 +     * <p>
 165.146 +     * FINE messages might include things like minor (recoverable)
 165.147 +     * failures.  Issues indicating potential performance problems
 165.148 +     * are also worth logging as FINE.
 165.149 +     * This level is initialized to <CODE>500</CODE>.
 165.150 +     */
 165.151 +    public static final Level FINE = new Level("FINE", 500, defaultBundle);
 165.152 +
 165.153 +    /**
 165.154 +     * FINER indicates a fairly detailed tracing message.
 165.155 +     * By default logging calls for entering, returning, or throwing
 165.156 +     * an exception are traced at this level.
 165.157 +     * This level is initialized to <CODE>400</CODE>.
 165.158 +     */
 165.159 +    public static final Level FINER = new Level("FINER", 400, defaultBundle);
 165.160 +
 165.161 +    /**
 165.162 +     * FINEST indicates a highly detailed tracing message.
 165.163 +     * This level is initialized to <CODE>300</CODE>.
 165.164 +     */
 165.165 +    public static final Level FINEST = new Level("FINEST", 300, defaultBundle);
 165.166 +
 165.167 +    /**
 165.168 +     * ALL indicates that all messages should be logged.
 165.169 +     * This level is initialized to <CODE>Integer.MIN_VALUE</CODE>.
 165.170 +     */
 165.171 +    public static final Level ALL = new Level("ALL", Integer.MIN_VALUE, defaultBundle);
 165.172 +
 165.173 +    /**
 165.174 +     * Create a named Level with a given integer value.
 165.175 +     * <p>
 165.176 +     * Note that this constructor is "protected" to allow subclassing.
 165.177 +     * In general clients of logging should use one of the constant Level
 165.178 +     * objects such as SEVERE or FINEST.  However, if clients need to
 165.179 +     * add new logging levels, they may subclass Level and define new
 165.180 +     * constants.
 165.181 +     * @param name  the name of the Level, for example "SEVERE".
 165.182 +     * @param value an integer value for the level.
 165.183 +     * @throws NullPointerException if the name is null
 165.184 +     */
 165.185 +    protected Level(String name, int value) {
 165.186 +        this(name, value, null);
 165.187 +    }
 165.188 +
 165.189 +    /**
 165.190 +     * Create a named Level with a given integer value and a
 165.191 +     * given localization resource name.
 165.192 +     * <p>
 165.193 +     * @param name  the name of the Level, for example "SEVERE".
 165.194 +     * @param value an integer value for the level.
 165.195 +     * @param resourceBundleName name of a resource bundle to use in
 165.196 +     *    localizing the given name. If the resourceBundleName is null
 165.197 +     *    or an empty string, it is ignored.
 165.198 +     * @throws NullPointerException if the name is null
 165.199 +     */
 165.200 +    protected Level(String name, int value, String resourceBundleName) {
 165.201 +        if (name == null) {
 165.202 +            throw new NullPointerException();
 165.203 +        }
 165.204 +        this.name = name;
 165.205 +        this.value = value;
 165.206 +        this.resourceBundleName = resourceBundleName;
 165.207 +        synchronized (Level.class) {
 165.208 +            known.add(this);
 165.209 +        }
 165.210 +    }
 165.211 +
 165.212 +    /**
 165.213 +     * Return the level's localization resource bundle name, or
 165.214 +     * null if no localization bundle is defined.
 165.215 +     *
 165.216 +     * @return localization resource bundle name
 165.217 +     */
 165.218 +    public String getResourceBundleName() {
 165.219 +        return resourceBundleName;
 165.220 +    }
 165.221 +
 165.222 +    /**
 165.223 +     * Return the non-localized string name of the Level.
 165.224 +     *
 165.225 +     * @return non-localized name
 165.226 +     */
 165.227 +    public String getName() {
 165.228 +        return name;
 165.229 +    }
 165.230 +
 165.231 +    /**
 165.232 +     * Return the localized string name of the Level, for
 165.233 +     * the current default locale.
 165.234 +     * <p>
 165.235 +     * If no localization information is available, the
 165.236 +     * non-localized name is returned.
 165.237 +     *
 165.238 +     * @return localized name
 165.239 +     */
 165.240 +    public String getLocalizedName() {
 165.241 +        return getName();
 165.242 +    }
 165.243 +
 165.244 +    /**
 165.245 +     * Returns a string representation of this Level.
 165.246 +     *
 165.247 +     * @return the non-localized name of the Level, for example "INFO".
 165.248 +     */
 165.249 +    public final String toString() {
 165.250 +        return name;
 165.251 +    }
 165.252 +
 165.253 +    /**
 165.254 +     * Get the integer value for this level.  This integer value
 165.255 +     * can be used for efficient ordering comparisons between
 165.256 +     * Level objects.
 165.257 +     * @return the integer value for this level.
 165.258 +     */
 165.259 +    public final int intValue() {
 165.260 +        return value;
 165.261 +    }
 165.262 +
 165.263 +    private static final long serialVersionUID = -8176160795706313070L;
 165.264 +
 165.265 +    // Serialization magic to prevent "doppelgangers".
 165.266 +    // This is a performance optimization.
 165.267 +    private Object readResolve() {
 165.268 +        synchronized (Level.class) {
 165.269 +            for (int i = 0; i < known.size(); i++) {
 165.270 +                Level other = known.get(i);
 165.271 +                if (this.name.equals(other.name) && this.value == other.value
 165.272 +                        && (this.resourceBundleName == other.resourceBundleName ||
 165.273 +                            (this.resourceBundleName != null &&
 165.274 +                            this.resourceBundleName.equals(other.resourceBundleName)))) {
 165.275 +                    return other;
 165.276 +                }
 165.277 +            }
 165.278 +            // Woops.  Whoever sent us this object knows
 165.279 +            // about a new log level.  Add it to our list.
 165.280 +            known.add(this);
 165.281 +            return this;
 165.282 +        }
 165.283 +    }
 165.284 +
 165.285 +    /**
 165.286 +     * Parse a level name string into a Level.
 165.287 +     * <p>
 165.288 +     * The argument string may consist of either a level name
 165.289 +     * or an integer value.
 165.290 +     * <p>
 165.291 +     * For example:
 165.292 +     * <ul>
 165.293 +     * <li>     "SEVERE"
 165.294 +     * <li>     "1000"
 165.295 +     * </ul>
 165.296 +     * @param  name   string to be parsed
 165.297 +     * @throws NullPointerException if the name is null
 165.298 +     * @throws IllegalArgumentException if the value is not valid.
 165.299 +     * Valid values are integers between <CODE>Integer.MIN_VALUE</CODE>
 165.300 +     * and <CODE>Integer.MAX_VALUE</CODE>, and all known level names.
 165.301 +     * Known names are the levels defined by this class (e.g., <CODE>FINE</CODE>,
 165.302 +     * <CODE>FINER</CODE>, <CODE>FINEST</CODE>), or created by this class with
 165.303 +     * appropriate package access, or new levels defined or created
 165.304 +     * by subclasses.
 165.305 +     *
 165.306 +     * @return The parsed value. Passing an integer that corresponds to a known name
 165.307 +     * (e.g., 700) will return the associated name (e.g., <CODE>CONFIG</CODE>).
 165.308 +     * Passing an integer that does not (e.g., 1) will return a new level name
 165.309 +     * initialized to that value.
 165.310 +     */
 165.311 +    public static synchronized Level parse(String name) throws IllegalArgumentException {
 165.312 +        // Check that name is not null.
 165.313 +        name.length();
 165.314 +
 165.315 +        // Look for a known Level with the given non-localized name.
 165.316 +        for (int i = 0; i < known.size(); i++) {
 165.317 +            Level l = known.get(i);
 165.318 +            if (name.equals(l.name)) {
 165.319 +                return l;
 165.320 +            }
 165.321 +        }
 165.322 +
 165.323 +        // Now, check if the given name is an integer.  If so,
 165.324 +        // first look for a Level with the given value and then
 165.325 +        // if necessary create one.
 165.326 +        try {
 165.327 +            int x = Integer.parseInt(name);
 165.328 +            for (int i = 0; i < known.size(); i++) {
 165.329 +                Level l = known.get(i);
 165.330 +                if (l.value == x) {
 165.331 +                    return l;
 165.332 +                }
 165.333 +            }
 165.334 +            // Create a new Level.
 165.335 +            return new Level(name, x);
 165.336 +        } catch (NumberFormatException ex) {
 165.337 +            // Not an integer.
 165.338 +            // Drop through.
 165.339 +        }
 165.340 +
 165.341 +        // Finally, look for a known level with the given localized name,
 165.342 +        // in the current default locale.
 165.343 +        // This is relatively expensive, but not excessively so.
 165.344 +        for (int i = 0; i < known.size(); i++) {
 165.345 +            Level l =  known.get(i);
 165.346 +            if (name.equals(l.getLocalizedName())) {
 165.347 +                return l;
 165.348 +            }
 165.349 +        }
 165.350 +
 165.351 +        // OK, we've tried everything and failed
 165.352 +        throw new IllegalArgumentException("Bad level \"" + name + "\"");
 165.353 +    }
 165.354 +
 165.355 +    /**
 165.356 +     * Compare two objects for value equality.
 165.357 +     * @return true if and only if the two objects have the same level value.
 165.358 +     */
 165.359 +    public boolean equals(Object ox) {
 165.360 +        try {
 165.361 +            Level lx = (Level)ox;
 165.362 +            return (lx.value == this.value);
 165.363 +        } catch (Exception ex) {
 165.364 +            return false;
 165.365 +        }
 165.366 +    }
 165.367 +
 165.368 +    /**
 165.369 +     * Generate a hashcode.
 165.370 +     * @return a hashcode based on the level value
 165.371 +     */
 165.372 +    public int hashCode() {
 165.373 +        return this.value;
 165.374 +    }
 165.375 +}
   166.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   166.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/LogRecord.java	Mon Oct 07 14:20:58 2013 +0200
   166.3 @@ -0,0 +1,468 @@
   166.4 +/*
   166.5 + * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
   166.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   166.7 + *
   166.8 + * This code is free software; you can redistribute it and/or modify it
   166.9 + * under the terms of the GNU General Public License version 2 only, as
  166.10 + * published by the Free Software Foundation.  Oracle designates this
  166.11 + * particular file as subject to the "Classpath" exception as provided
  166.12 + * by Oracle in the LICENSE file that accompanied this code.
  166.13 + *
  166.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  166.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  166.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  166.17 + * version 2 for more details (a copy is included in the LICENSE file that
  166.18 + * accompanied this code).
  166.19 + *
  166.20 + * You should have received a copy of the GNU General Public License version
  166.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  166.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  166.23 + *
  166.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  166.25 + * or visit www.oracle.com if you need additional information or have any
  166.26 + * questions.
  166.27 + */
  166.28 +
  166.29 +package java.util.logging;
  166.30 +import java.io.*;
  166.31 +
  166.32 +/**
  166.33 + * LogRecord objects are used to pass logging requests between
  166.34 + * the logging framework and individual log Handlers.
  166.35 + * <p>
  166.36 + * When a LogRecord is passed into the logging framework it
  166.37 + * logically belongs to the framework and should no longer be
  166.38 + * used or updated by the client application.
  166.39 + * <p>
  166.40 + * Note that if the client application has not specified an
  166.41 + * explicit source method name and source class name, then the
  166.42 + * LogRecord class will infer them automatically when they are
  166.43 + * first accessed (due to a call on getSourceMethodName or
  166.44 + * getSourceClassName) by analyzing the call stack.  Therefore,
  166.45 + * if a logging Handler wants to pass off a LogRecord to another
  166.46 + * thread, or to transmit it over RMI, and if it wishes to subsequently
  166.47 + * obtain method name or class name information it should call
  166.48 + * one of getSourceClassName or getSourceMethodName to force
  166.49 + * the values to be filled in.
  166.50 + * <p>
  166.51 + * <b> Serialization notes:</b>
  166.52 + * <ul>
  166.53 + * <li>The LogRecord class is serializable.
  166.54 + *
  166.55 + * <li> Because objects in the parameters array may not be serializable,
  166.56 + * during serialization all objects in the parameters array are
  166.57 + * written as the corresponding Strings (using Object.toString).
  166.58 + *
  166.59 + * <li> The ResourceBundle is not transmitted as part of the serialized
  166.60 + * form, but the resource bundle name is, and the recipient object's
  166.61 + * readObject method will attempt to locate a suitable resource bundle.
  166.62 + *
  166.63 + * </ul>
  166.64 + *
  166.65 + * @since 1.4
  166.66 + */
  166.67 +
  166.68 +public class LogRecord implements java.io.Serializable {
  166.69 +    private static long globalSequenceNumber = 0;
  166.70 +
  166.71 +    /**
  166.72 +     * The default value of threadID will be the current thread's
  166.73 +     * thread id, for ease of correlation, unless it is greater than
  166.74 +     * MIN_SEQUENTIAL_THREAD_ID, in which case we try harder to keep
  166.75 +     * our promise to keep threadIDs unique by avoiding collisions due
  166.76 +     * to 32-bit wraparound.  Unfortunately, LogRecord.getThreadID()
  166.77 +     * returns int, while Thread.getId() returns long.
  166.78 +     */
  166.79 +    private static final int MIN_SEQUENTIAL_THREAD_ID = Integer.MAX_VALUE / 2;
  166.80 +
  166.81 +    /**
  166.82 +     * @serial Logging message level
  166.83 +     */
  166.84 +    private Level level;
  166.85 +
  166.86 +    /**
  166.87 +     * @serial Sequence number
  166.88 +     */
  166.89 +    private long sequenceNumber;
  166.90 +
  166.91 +    /**
  166.92 +     * @serial Class that issued logging call
  166.93 +     */
  166.94 +    private String sourceClassName;
  166.95 +
  166.96 +    /**
  166.97 +     * @serial Method that issued logging call
  166.98 +     */
  166.99 +    private String sourceMethodName;
 166.100 +
 166.101 +    /**
 166.102 +     * @serial Non-localized raw message text
 166.103 +     */
 166.104 +    private String message;
 166.105 +
 166.106 +    /**
 166.107 +     * @serial Thread ID for thread that issued logging call.
 166.108 +     */
 166.109 +    private int threadID;
 166.110 +
 166.111 +    /**
 166.112 +     * @serial Event time in milliseconds since 1970
 166.113 +     */
 166.114 +    private long millis;
 166.115 +
 166.116 +    /**
 166.117 +     * @serial The Throwable (if any) associated with log message
 166.118 +     */
 166.119 +    private Throwable thrown;
 166.120 +
 166.121 +    /**
 166.122 +     * @serial Name of the source Logger.
 166.123 +     */
 166.124 +    private String loggerName;
 166.125 +
 166.126 +    /**
 166.127 +     * @serial Resource bundle name to localized log message.
 166.128 +     */
 166.129 +    private String resourceBundleName;
 166.130 +
 166.131 +    private transient boolean needToInferCaller;
 166.132 +    private transient Object parameters[];
 166.133 +
 166.134 +    /**
 166.135 +     * Returns the default value for a new LogRecord's threadID.
 166.136 +     */
 166.137 +    private int defaultThreadID() {
 166.138 +        return 0;
 166.139 +    }
 166.140 +
 166.141 +    /**
 166.142 +     * Construct a LogRecord with the given level and message values.
 166.143 +     * <p>
 166.144 +     * The sequence property will be initialized with a new unique value.
 166.145 +     * These sequence values are allocated in increasing order within a VM.
 166.146 +     * <p>
 166.147 +     * The millis property will be initialized to the current time.
 166.148 +     * <p>
 166.149 +     * The thread ID property will be initialized with a unique ID for
 166.150 +     * the current thread.
 166.151 +     * <p>
 166.152 +     * All other properties will be initialized to "null".
 166.153 +     *
 166.154 +     * @param level  a logging level value
 166.155 +     * @param msg  the raw non-localized logging message (may be null)
 166.156 +     */
 166.157 +    public LogRecord(Level level, String msg) {
 166.158 +        // Make sure level isn't null, by calling random method.
 166.159 +        level.getClass();
 166.160 +        this.level = level;
 166.161 +        message = msg;
 166.162 +        // Assign a thread ID and a unique sequence number.
 166.163 +        sequenceNumber = globalSequenceNumber++;
 166.164 +        threadID = defaultThreadID();
 166.165 +        millis = System.currentTimeMillis();
 166.166 +        needToInferCaller = true;
 166.167 +   }
 166.168 +
 166.169 +    /**
 166.170 +     * Get the source Logger's name.
 166.171 +     *
 166.172 +     * @return source logger name (may be null)
 166.173 +     */
 166.174 +    public String getLoggerName() {
 166.175 +        return loggerName;
 166.176 +    }
 166.177 +
 166.178 +    /**
 166.179 +     * Set the source Logger's name.
 166.180 +     *
 166.181 +     * @param name   the source logger name (may be null)
 166.182 +     */
 166.183 +    public void setLoggerName(String name) {
 166.184 +        loggerName = name;
 166.185 +    }
 166.186 +
 166.187 +    /**
 166.188 +     * Get the localization resource bundle
 166.189 +     * <p>
 166.190 +     * This is the ResourceBundle that should be used to localize
 166.191 +     * the message string before formatting it.  The result may
 166.192 +     * be null if the message is not localizable, or if no suitable
 166.193 +     * ResourceBundle is available.
 166.194 +     */
 166.195 +//    public ResourceBundle getResourceBundle() {
 166.196 +//        return resourceBundle;
 166.197 +//    }
 166.198 +
 166.199 +    /**
 166.200 +     * Set the localization resource bundle.
 166.201 +     *
 166.202 +     * @param bundle  localization bundle (may be null)
 166.203 +     */
 166.204 +//    public void setResourceBundle(ResourceBundle bundle) {
 166.205 +//        resourceBundle = bundle;
 166.206 +//    }
 166.207 +
 166.208 +    /**
 166.209 +     * Get the localization resource bundle name
 166.210 +     * <p>
 166.211 +     * This is the name for the ResourceBundle that should be
 166.212 +     * used to localize the message string before formatting it.
 166.213 +     * The result may be null if the message is not localizable.
 166.214 +     */
 166.215 +    public String getResourceBundleName() {
 166.216 +        return resourceBundleName;
 166.217 +    }
 166.218 +
 166.219 +    /**
 166.220 +     * Set the localization resource bundle name.
 166.221 +     *
 166.222 +     * @param name  localization bundle name (may be null)
 166.223 +     */
 166.224 +    public void setResourceBundleName(String name) {
 166.225 +        resourceBundleName = name;
 166.226 +    }
 166.227 +
 166.228 +    /**
 166.229 +     * Get the logging message level, for example Level.SEVERE.
 166.230 +     * @return the logging message level
 166.231 +     */
 166.232 +    public Level getLevel() {
 166.233 +        return level;
 166.234 +    }
 166.235 +
 166.236 +    /**
 166.237 +     * Set the logging message level, for example Level.SEVERE.
 166.238 +     * @param level the logging message level
 166.239 +     */
 166.240 +    public void setLevel(Level level) {
 166.241 +        if (level == null) {
 166.242 +            throw new NullPointerException();
 166.243 +        }
 166.244 +        this.level = level;
 166.245 +    }
 166.246 +
 166.247 +    /**
 166.248 +     * Get the sequence number.
 166.249 +     * <p>
 166.250 +     * Sequence numbers are normally assigned in the LogRecord
 166.251 +     * constructor, which assigns unique sequence numbers to
 166.252 +     * each new LogRecord in increasing order.
 166.253 +     * @return the sequence number
 166.254 +     */
 166.255 +    public long getSequenceNumber() {
 166.256 +        return sequenceNumber;
 166.257 +    }
 166.258 +
 166.259 +    /**
 166.260 +     * Set the sequence number.
 166.261 +     * <p>
 166.262 +     * Sequence numbers are normally assigned in the LogRecord constructor,
 166.263 +     * so it should not normally be necessary to use this method.
 166.264 +     */
 166.265 +    public void setSequenceNumber(long seq) {
 166.266 +        sequenceNumber = seq;
 166.267 +    }
 166.268 +
 166.269 +    /**
 166.270 +     * Get the  name of the class that (allegedly) issued the logging request.
 166.271 +     * <p>
 166.272 +     * Note that this sourceClassName is not verified and may be spoofed.
 166.273 +     * This information may either have been provided as part of the
 166.274 +     * logging call, or it may have been inferred automatically by the
 166.275 +     * logging framework.  In the latter case, the information may only
 166.276 +     * be approximate and may in fact describe an earlier call on the
 166.277 +     * stack frame.
 166.278 +     * <p>
 166.279 +     * May be null if no information could be obtained.
 166.280 +     *
 166.281 +     * @return the source class name
 166.282 +     */
 166.283 +    public String getSourceClassName() {
 166.284 +        return sourceClassName;
 166.285 +    }
 166.286 +
 166.287 +    /**
 166.288 +     * Set the name of the class that (allegedly) issued the logging request.
 166.289 +     *
 166.290 +     * @param sourceClassName the source class name (may be null)
 166.291 +     */
 166.292 +    public void setSourceClassName(String sourceClassName) {
 166.293 +        this.sourceClassName = sourceClassName;
 166.294 +        needToInferCaller = false;
 166.295 +    }
 166.296 +
 166.297 +    /**
 166.298 +     * Get the  name of the method that (allegedly) issued the logging request.
 166.299 +     * <p>
 166.300 +     * Note that this sourceMethodName is not verified and may be spoofed.
 166.301 +     * This information may either have been provided as part of the
 166.302 +     * logging call, or it may have been inferred automatically by the
 166.303 +     * logging framework.  In the latter case, the information may only
 166.304 +     * be approximate and may in fact describe an earlier call on the
 166.305 +     * stack frame.
 166.306 +     * <p>
 166.307 +     * May be null if no information could be obtained.
 166.308 +     *
 166.309 +     * @return the source method name
 166.310 +     */
 166.311 +    public String getSourceMethodName() {
 166.312 +        return sourceMethodName;
 166.313 +    }
 166.314 +
 166.315 +    /**
 166.316 +     * Set the name of the method that (allegedly) issued the logging request.
 166.317 +     *
 166.318 +     * @param sourceMethodName the source method name (may be null)
 166.319 +     */
 166.320 +    public void setSourceMethodName(String sourceMethodName) {
 166.321 +        this.sourceMethodName = sourceMethodName;
 166.322 +        needToInferCaller = false;
 166.323 +    }
 166.324 +
 166.325 +    /**
 166.326 +     * Get the "raw" log message, before localization or formatting.
 166.327 +     * <p>
 166.328 +     * May be null, which is equivalent to the empty string "".
 166.329 +     * <p>
 166.330 +     * This message may be either the final text or a localization key.
 166.331 +     * <p>
 166.332 +     * During formatting, if the source logger has a localization
 166.333 +     * ResourceBundle and if that ResourceBundle has an entry for
 166.334 +     * this message string, then the message string is replaced
 166.335 +     * with the localized value.
 166.336 +     *
 166.337 +     * @return the raw message string
 166.338 +     */
 166.339 +    public String getMessage() {
 166.340 +        return message;
 166.341 +    }
 166.342 +
 166.343 +    /**
 166.344 +     * Set the "raw" log message, before localization or formatting.
 166.345 +     *
 166.346 +     * @param message the raw message string (may be null)
 166.347 +     */
 166.348 +    public void setMessage(String message) {
 166.349 +        this.message = message;
 166.350 +    }
 166.351 +
 166.352 +    /**
 166.353 +     * Get the parameters to the log message.
 166.354 +     *
 166.355 +     * @return the log message parameters.  May be null if
 166.356 +     *                  there are no parameters.
 166.357 +     */
 166.358 +    public Object[] getParameters() {
 166.359 +        return parameters;
 166.360 +    }
 166.361 +
 166.362 +    /**
 166.363 +     * Set the parameters to the log message.
 166.364 +     *
 166.365 +     * @param parameters the log message parameters. (may be null)
 166.366 +     */
 166.367 +    public void setParameters(Object parameters[]) {
 166.368 +        this.parameters = parameters;
 166.369 +    }
 166.370 +
 166.371 +    /**
 166.372 +     * Get an identifier for the thread where the message originated.
 166.373 +     * <p>
 166.374 +     * This is a thread identifier within the Java VM and may or
 166.375 +     * may not map to any operating system ID.
 166.376 +     *
 166.377 +     * @return thread ID
 166.378 +     */
 166.379 +    public int getThreadID() {
 166.380 +        return threadID;
 166.381 +    }
 166.382 +
 166.383 +    /**
 166.384 +     * Set an identifier for the thread where the message originated.
 166.385 +     * @param threadID  the thread ID
 166.386 +     */
 166.387 +    public void setThreadID(int threadID) {
 166.388 +        this.threadID = threadID;
 166.389 +    }
 166.390 +
 166.391 +    /**
 166.392 +     * Get event time in milliseconds since 1970.
 166.393 +     *
 166.394 +     * @return event time in millis since 1970
 166.395 +     */
 166.396 +    public long getMillis() {
 166.397 +        return millis;
 166.398 +    }
 166.399 +
 166.400 +    /**
 166.401 +     * Set event time.
 166.402 +     *
 166.403 +     * @param millis event time in millis since 1970
 166.404 +     */
 166.405 +    public void setMillis(long millis) {
 166.406 +        this.millis = millis;
 166.407 +    }
 166.408 +
 166.409 +    /**
 166.410 +     * Get any throwable associated with the log record.
 166.411 +     * <p>
 166.412 +     * If the event involved an exception, this will be the
 166.413 +     * exception object. Otherwise null.
 166.414 +     *
 166.415 +     * @return a throwable
 166.416 +     */
 166.417 +    public Throwable getThrown() {
 166.418 +        return thrown;
 166.419 +    }
 166.420 +
 166.421 +    /**
 166.422 +     * Set a throwable associated with the log event.
 166.423 +     *
 166.424 +     * @param thrown  a throwable (may be null)
 166.425 +     */
 166.426 +    public void setThrown(Throwable thrown) {
 166.427 +        this.thrown = thrown;
 166.428 +    }
 166.429 +
 166.430 +    private static final long serialVersionUID = 5372048053134512534L;
 166.431 +
 166.432 +    /**
 166.433 +     * @serialData Default fields, followed by a two byte version number
 166.434 +     * (major byte, followed by minor byte), followed by information on
 166.435 +     * the log record parameter array.  If there is no parameter array,
 166.436 +     * then -1 is written.  If there is a parameter array (possible of zero
 166.437 +     * length) then the array length is written as an integer, followed
 166.438 +     * by String values for each parameter.  If a parameter is null, then
 166.439 +     * a null String is written.  Otherwise the output of Object.toString()
 166.440 +     * is written.
 166.441 +     */
 166.442 +    private void writeObject(ObjectOutputStream out) throws IOException {
 166.443 +        // We have to call defaultWriteObject first.
 166.444 +        out.defaultWriteObject();
 166.445 +
 166.446 +        // Write our version number.
 166.447 +        out.writeByte(1);
 166.448 +        out.writeByte(0);
 166.449 +        if (parameters == null) {
 166.450 +            out.writeInt(-1);
 166.451 +            return;
 166.452 +        }
 166.453 +        out.writeInt(parameters.length);
 166.454 +        // Write string values for the parameters.
 166.455 +        for (int i = 0; i < parameters.length; i++) {
 166.456 +            if (parameters[i] == null) {
 166.457 +                out.writeObject(null);
 166.458 +            } else {
 166.459 +                out.writeObject(parameters[i].toString());
 166.460 +            }
 166.461 +        }
 166.462 +    }
 166.463 +
 166.464 +
 166.465 +    private boolean isLoggerImplFrame(String cname) {
 166.466 +        // the log record could be created for a platform logger
 166.467 +        return (cname.equals("java.util.logging.Logger") ||
 166.468 +                cname.startsWith("java.util.logging.LoggingProxyImpl") ||
 166.469 +                cname.startsWith("sun.util.logging."));
 166.470 +    }
 166.471 +}
   167.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   167.2 +++ b/rt/emul/compact/src/main/java/java/util/logging/Logger.java	Mon Oct 07 14:20:58 2013 +0200
   167.3 @@ -0,0 +1,1258 @@
   167.4 +/*
   167.5 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
   167.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   167.7 + *
   167.8 + * This code is free software; you can redistribute it and/or modify it
   167.9 + * under the terms of the GNU General Public License version 2 only, as
  167.10 + * published by the Free Software Foundation.  Oracle designates this
  167.11 + * particular file as subject to the "Classpath" exception as provided
  167.12 + * by Oracle in the LICENSE file that accompanied this code.
  167.13 + *
  167.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  167.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  167.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  167.17 + * version 2 for more details (a copy is included in the LICENSE file that
  167.18 + * accompanied this code).
  167.19 + *
  167.20 + * You should have received a copy of the GNU General Public License version
  167.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  167.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  167.23 + *
  167.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  167.25 + * or visit www.oracle.com if you need additional information or have any
  167.26 + * questions.
  167.27 + */
  167.28 +
  167.29 +
  167.30 +package java.util.logging;
  167.31 +
  167.32 +import java.util.HashMap;
  167.33 +import java.util.Map;
  167.34 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  167.35 +
  167.36 +/**
  167.37 + * A Logger object is used to log messages for a specific
  167.38 + * system or application component.  Loggers are normally named,
  167.39 + * using a hierarchical dot-separated namespace.  Logger names
  167.40 + * can be arbitrary strings, but they should normally be based on
  167.41 + * the package name or class name of the logged component, such
  167.42 + * as java.net or javax.swing.  In addition it is possible to create
  167.43 + * "anonymous" Loggers that are not stored in the Logger namespace.
  167.44 + * <p>
  167.45 + * Logger objects may be obtained by calls on one of the getLogger
  167.46 + * factory methods.  These will either create a new Logger or
  167.47 + * return a suitable existing Logger. It is important to note that
  167.48 + * the Logger returned by one of the {@code getLogger} factory methods
  167.49 + * may be garbage collected at any time if a strong reference to the
  167.50 + * Logger is not kept.
  167.51 + * <p>
  167.52 + * Logging messages will be forwarded to registered Handler
  167.53 + * objects, which can forward the messages to a variety of
  167.54 + * destinations, including consoles, files, OS logs, etc.
  167.55 + * <p>
  167.56 + * Each Logger keeps track of a "parent" Logger, which is its
  167.57 + * nearest existing ancestor in the Logger namespace.
  167.58 + * <p>
  167.59 + * Each Logger has a "Level" associated with it.  This reflects
  167.60 + * a minimum Level that this logger cares about.  If a Logger's
  167.61 + * level is set to <tt>null</tt>, then its effective level is inherited
  167.62 + * from its parent, which may in turn obtain it recursively from its
  167.63 + * parent, and so on up the tree.
  167.64 + * <p>
  167.65 + * The log level can be configured based on the properties from the
  167.66 + * logging configuration file, as described in the description
  167.67 + * of the LogManager class.  However it may also be dynamically changed
  167.68 + * by calls on the Logger.setLevel method.  If a logger's level is
  167.69 + * changed the change may also affect child loggers, since any child
  167.70 + * logger that has <tt>null</tt> as its level will inherit its
  167.71 + * effective level from its parent.
  167.72 + * <p>
  167.73 + * On each logging call the Logger initially performs a cheap
  167.74 + * check of the request level (e.g., SEVERE or FINE) against the
  167.75 + * effective log level of the logger.  If the request level is
  167.76 + * lower than the log level, the logging call returns immediately.
  167.77 + * <p>
  167.78 + * After passing this initial (cheap) test, the Logger will allocate
  167.79 + * a LogRecord to describe the logging message.  It will then call a
  167.80 + * Filter (if present) to do a more detailed check on whether the
  167.81 + * record should be published.  If that passes it will then publish
  167.82 + * the LogRecord to its output Handlers.  By default, loggers also
  167.83 + * publish to their parent's Handlers, recursively up the tree.
  167.84 + * <p>
  167.85 + * Each Logger may have a ResourceBundle name associated with it.
  167.86 + * The named bundle will be used for localizing logging messages.
  167.87 + * If a Logger does not have its own ResourceBundle name, then
  167.88 + * it will inherit the ResourceBundle name from its parent,
  167.89 + * recursively up the tree.
  167.90 + * <p>
  167.91 + * Most of the logger output methods take a "msg" argument.  This
  167.92 + * msg argument may be either a raw value or a localization key.
  167.93 + * During formatting, if the logger has (or inherits) a localization
  167.94 + * ResourceBundle and if the ResourceBundle has a mapping for the msg
  167.95 + * string, then the msg string is replaced by the localized value.
  167.96 + * Otherwise the original msg string is used.  Typically, formatters use
  167.97 + * java.text.MessageFormat style formatting to format parameters, so
  167.98 + * for example a format string "{0} {1}" would format two parameters
  167.99 + * as strings.
 167.100 + * <p>
 167.101 + * When mapping ResourceBundle names to ResourceBundles, the Logger
 167.102 + * will first try to use the Thread's ContextClassLoader.  If that
 167.103 + * is null it will try the SystemClassLoader instead.  As a temporary
 167.104 + * transition feature in the initial implementation, if the Logger is
 167.105 + * unable to locate a ResourceBundle from the ContextClassLoader or
 167.106 + * SystemClassLoader the Logger will also search up the class stack
 167.107 + * and use successive calling ClassLoaders to try to locate a ResourceBundle.
 167.108 + * (This call stack search is to allow containers to transition to
 167.109 + * using ContextClassLoaders and is likely to be removed in future
 167.110 + * versions.)
 167.111 + * <p>
 167.112 + * Formatting (including localization) is the responsibility of
 167.113 + * the output Handler, which will typically call a Formatter.
 167.114 + * <p>
 167.115 + * Note that formatting need not occur synchronously.  It may be delayed
 167.116 + * until a LogRecord is actually written to an external sink.
 167.117 + * <p>
 167.118 + * The logging methods are grouped in five main categories:
 167.119 + * <ul>
 167.120 + * <li><p>
 167.121 + *     There are a set of "log" methods that take a log level, a message
 167.122 + *     string, and optionally some parameters to the message string.
 167.123 + * <li><p>
 167.124 + *     There are a set of "logp" methods (for "log precise") that are
 167.125 + *     like the "log" methods, but also take an explicit source class name
 167.126 + *     and method name.
 167.127 + * <li><p>
 167.128 + *     There are a set of "logrb" method (for "log with resource bundle")
 167.129 + *     that are like the "logp" method, but also take an explicit resource
 167.130 + *     bundle name for use in localizing the log message.
 167.131 + * <li><p>
 167.132 + *     There are convenience methods for tracing method entries (the
 167.133 + *     "entering" methods), method returns (the "exiting" methods) and
 167.134 + *     throwing exceptions (the "throwing" methods).
 167.135 + * <li><p>
 167.136 + *     Finally, there are a set of convenience methods for use in the
 167.137 + *     very simplest cases, when a developer simply wants to log a
 167.138 + *     simple string at a given log level.  These methods are named
 167.139 + *     after the standard Level names ("severe", "warning", "info", etc.)
 167.140 + *     and take a single argument, a message string.
 167.141 + * </ul>
 167.142 + * <p>
 167.143 + * For the methods that do not take an explicit source name and
 167.144 + * method name, the Logging framework will make a "best effort"
 167.145 + * to determine which class and method called into the logging method.
 167.146 + * However, it is important to realize that this automatically inferred
 167.147 + * information may only be approximate (or may even be quite wrong!).
 167.148 + * Virtual machines are allowed to do extensive optimizations when
 167.149 + * JITing and may entirely remove stack frames, making it impossible
 167.150 + * to reliably locate the calling class and method.
 167.151 + * <P>
 167.152 + * All methods on Logger are multi-thread safe.
 167.153 + * <p>
 167.154 + * <b>Subclassing Information:</b> Note that a LogManager class may
 167.155 + * provide its own implementation of named Loggers for any point in
 167.156 + * the namespace.  Therefore, any subclasses of Logger (unless they
 167.157 + * are implemented in conjunction with a new LogManager class) should
 167.158 + * take care to obtain a Logger instance from the LogManager class and
 167.159 + * should delegate operations such as "isLoggable" and "log(LogRecord)"
 167.160 + * to that instance.  Note that in order to intercept all logging
 167.161 + * output, subclasses need only override the log(LogRecord) method.
 167.162 + * All the other logging methods are implemented as calls on this
 167.163 + * log(LogRecord) method.
 167.164 + *
 167.165 + * @since 1.4
 167.166 + */
 167.167 +
 167.168 +
 167.169 +public class Logger {
 167.170 +    private static int offValue = Level.OFF.intValue();
 167.171 +    private static final Map<String,Logger> ALL = new HashMap<>();
 167.172 +    private String name;
 167.173 +
 167.174 +    private volatile int levelValue;  // current effective level value
 167.175 +    private Level levelObject;
 167.176 +    
 167.177 +    /**
 167.178 +     * GLOBAL_LOGGER_NAME is a name for the global logger.
 167.179 +     *
 167.180 +     * @since 1.6
 167.181 +     */
 167.182 +    public static final String GLOBAL_LOGGER_NAME = "global";
 167.183 +
 167.184 +    /**
 167.185 +     * Return global logger object with the name Logger.GLOBAL_LOGGER_NAME.
 167.186 +     *
 167.187 +     * @return global logger object
 167.188 +     * @since 1.7
 167.189 +     */
 167.190 +    public static final Logger getGlobal() {
 167.191 +        return global;
 167.192 +    }
 167.193 +
 167.194 +    /**
 167.195 +     * The "global" Logger object is provided as a convenience to developers
 167.196 +     * who are making casual use of the Logging package.  Developers
 167.197 +     * who are making serious use of the logging package (for example
 167.198 +     * in products) should create and use their own Logger objects,
 167.199 +     * with appropriate names, so that logging can be controlled on a
 167.200 +     * suitable per-Logger granularity. Developers also need to keep a
 167.201 +     * strong reference to their Logger objects to prevent them from
 167.202 +     * being garbage collected.
 167.203 +     * <p>
 167.204 +     * @deprecated Initialization of this field is prone to deadlocks.
 167.205 +     * The field must be initialized by the Logger class initialization
 167.206 +     * which may cause deadlocks with the LogManager class initialization.
 167.207 +     * In such cases two class initialization wait for each other to complete.
 167.208 +     * The preferred way to get the global logger object is via the call
 167.209 +     * <code>Logger.getGlobal()</code>.
 167.210 +     * For compatibility with old JDK versions where the
 167.211 +     * <code>Logger.getGlobal()</code> is not available use the call
 167.212 +     * <code>Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)</code>
 167.213 +     * or <code>Logger.getLogger("global")</code>.
 167.214 +     */
 167.215 +    @Deprecated
 167.216 +    public static final Logger global = new Logger(GLOBAL_LOGGER_NAME);
 167.217 +
 167.218 +    /**
 167.219 +     * Protected method to construct a logger for a named subsystem.
 167.220 +     * <p>
 167.221 +     * The logger will be initially configured with a null Level
 167.222 +     * and with useParentHandlers set to true.
 167.223 +     *
 167.224 +     * @param   name    A name for the logger.  This should
 167.225 +     *                          be a dot-separated name and should normally
 167.226 +     *                          be based on the package name or class name
 167.227 +     *                          of the subsystem, such as java.net
 167.228 +     *                          or javax.swing.  It may be null for anonymous Loggers.
 167.229 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 167.230 +     *                          messages for this logger.  May be null if none
 167.231 +     *                          of the messages require localization.
 167.232 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 167.233 +     *             no corresponding resource can be found.
 167.234 +     */
 167.235 +    protected Logger(String name, String resourceBundleName) {
 167.236 +        this.name = name;
 167.237 +        levelValue = Level.INFO.intValue();
 167.238 +    }
 167.239 +
 167.240 +    // This constructor is used only to create the global Logger.
 167.241 +    // It is needed to break a cyclic dependence between the LogManager
 167.242 +    // and Logger static initializers causing deadlocks.
 167.243 +    private Logger(String name) {
 167.244 +        // The manager field is not initialized here.
 167.245 +        this.name = name;
 167.246 +        levelValue = Level.INFO.intValue();
 167.247 +    }
 167.248 +
 167.249 +    private void checkAccess() throws SecurityException {
 167.250 +        throw new SecurityException();
 167.251 +    }
 167.252 +
 167.253 +    /**
 167.254 +     * Find or create a logger for a named subsystem.  If a logger has
 167.255 +     * already been created with the given name it is returned.  Otherwise
 167.256 +     * a new logger is created.
 167.257 +     * <p>
 167.258 +     * If a new logger is created its log level will be configured
 167.259 +     * based on the LogManager configuration and it will configured
 167.260 +     * to also send logging output to its parent's Handlers.  It will
 167.261 +     * be registered in the LogManager global namespace.
 167.262 +     * <p>
 167.263 +     * Note: The LogManager may only retain a weak reference to the newly
 167.264 +     * created Logger. It is important to understand that a previously
 167.265 +     * created Logger with the given name may be garbage collected at any
 167.266 +     * time if there is no strong reference to the Logger. In particular,
 167.267 +     * this means that two back-to-back calls like
 167.268 +     * {@code getLogger("MyLogger").log(...)} may use different Logger
 167.269 +     * objects named "MyLogger" if there is no strong reference to the
 167.270 +     * Logger named "MyLogger" elsewhere in the program.
 167.271 +     *
 167.272 +     * @param   name            A name for the logger.  This should
 167.273 +     *                          be a dot-separated name and should normally
 167.274 +     *                          be based on the package name or class name
 167.275 +     *                          of the subsystem, such as java.net
 167.276 +     *                          or javax.swing
 167.277 +     * @return a suitable Logger
 167.278 +     * @throws NullPointerException if the name is null.
 167.279 +     */
 167.280 +
 167.281 +    // Synchronization is not required here. All synchronization for
 167.282 +    // adding a new Logger object is handled by LogManager.addLogger().
 167.283 +    public static Logger getLogger(String name) {
 167.284 +        return getLogger(name, null);
 167.285 +    }
 167.286 +
 167.287 +    /**
 167.288 +     * Find or create a logger for a named subsystem.  If a logger has
 167.289 +     * already been created with the given name it is returned.  Otherwise
 167.290 +     * a new logger is created.
 167.291 +     * <p>
 167.292 +     * If a new logger is created its log level will be configured
 167.293 +     * based on the LogManager and it will configured to also send logging
 167.294 +     * output to its parent's Handlers.  It will be registered in
 167.295 +     * the LogManager global namespace.
 167.296 +     * <p>
 167.297 +     * Note: The LogManager may only retain a weak reference to the newly
 167.298 +     * created Logger. It is important to understand that a previously
 167.299 +     * created Logger with the given name may be garbage collected at any
 167.300 +     * time if there is no strong reference to the Logger. In particular,
 167.301 +     * this means that two back-to-back calls like
 167.302 +     * {@code getLogger("MyLogger", ...).log(...)} may use different Logger
 167.303 +     * objects named "MyLogger" if there is no strong reference to the
 167.304 +     * Logger named "MyLogger" elsewhere in the program.
 167.305 +     * <p>
 167.306 +     * If the named Logger already exists and does not yet have a
 167.307 +     * localization resource bundle then the given resource bundle
 167.308 +     * name is used.  If the named Logger already exists and has
 167.309 +     * a different resource bundle name then an IllegalArgumentException
 167.310 +     * is thrown.
 167.311 +     * <p>
 167.312 +     * @param   name    A name for the logger.  This should
 167.313 +     *                          be a dot-separated name and should normally
 167.314 +     *                          be based on the package name or class name
 167.315 +     *                          of the subsystem, such as java.net
 167.316 +     *                          or javax.swing
 167.317 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 167.318 +     *                          messages for this logger. May be <CODE>null</CODE> if none of
 167.319 +     *                          the messages require localization.
 167.320 +     * @return a suitable Logger
 167.321 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 167.322 +     *             no corresponding resource can be found.
 167.323 +     * @throws IllegalArgumentException if the Logger already exists and uses
 167.324 +     *             a different resource bundle name.
 167.325 +     * @throws NullPointerException if the name is null.
 167.326 +     */
 167.327 +
 167.328 +    // Synchronization is not required here. All synchronization for
 167.329 +    // adding a new Logger object is handled by LogManager.addLogger().
 167.330 +    public static Logger getLogger(String name, String resourceBundleName) {
 167.331 +        Logger l = ALL.get(name);
 167.332 +        if (l == null) {
 167.333 +            l = new Logger(name, resourceBundleName);
 167.334 +            ALL.put(name, l);
 167.335 +        }
 167.336 +        return l;
 167.337 +    }
 167.338 +
 167.339 +
 167.340 +    /**
 167.341 +     * Create an anonymous Logger.  The newly created Logger is not
 167.342 +     * registered in the LogManager namespace.  There will be no
 167.343 +     * access checks on updates to the logger.
 167.344 +     * <p>
 167.345 +     * This factory method is primarily intended for use from applets.
 167.346 +     * Because the resulting Logger is anonymous it can be kept private
 167.347 +     * by the creating class.  This removes the need for normal security
 167.348 +     * checks, which in turn allows untrusted applet code to update
 167.349 +     * the control state of the Logger.  For example an applet can do
 167.350 +     * a setLevel or an addHandler on an anonymous Logger.
 167.351 +     * <p>
 167.352 +     * Even although the new logger is anonymous, it is configured
 167.353 +     * to have the root logger ("") as its parent.  This means that
 167.354 +     * by default it inherits its effective level and handlers
 167.355 +     * from the root logger.
 167.356 +     * <p>
 167.357 +     *
 167.358 +     * @return a newly created private Logger
 167.359 +     */
 167.360 +    public static Logger getAnonymousLogger() {
 167.361 +        return getAnonymousLogger(null);
 167.362 +    }
 167.363 +
 167.364 +    /**
 167.365 +     * Create an anonymous Logger.  The newly created Logger is not
 167.366 +     * registered in the LogManager namespace.  There will be no
 167.367 +     * access checks on updates to the logger.
 167.368 +     * <p>
 167.369 +     * This factory method is primarily intended for use from applets.
 167.370 +     * Because the resulting Logger is anonymous it can be kept private
 167.371 +     * by the creating class.  This removes the need for normal security
 167.372 +     * checks, which in turn allows untrusted applet code to update
 167.373 +     * the control state of the Logger.  For example an applet can do
 167.374 +     * a setLevel or an addHandler on an anonymous Logger.
 167.375 +     * <p>
 167.376 +     * Even although the new logger is anonymous, it is configured
 167.377 +     * to have the root logger ("") as its parent.  This means that
 167.378 +     * by default it inherits its effective level and handlers
 167.379 +     * from the root logger.
 167.380 +     * <p>
 167.381 +     * @param   resourceBundleName  name of ResourceBundle to be used for localizing
 167.382 +     *                          messages for this logger.
 167.383 +     *          May be null if none of the messages require localization.
 167.384 +     * @return a newly created private Logger
 167.385 +     * @throws MissingResourceException if the resourceBundleName is non-null and
 167.386 +     *             no corresponding resource can be found.
 167.387 +     */
 167.388 +
 167.389 +    // Synchronization is not required here. All synchronization for
 167.390 +    // adding a new anonymous Logger object is handled by doSetParent().
 167.391 +    public static Logger getAnonymousLogger(String resourceBundleName) {
 167.392 +        return new Logger(null, resourceBundleName);
 167.393 +    }
 167.394 +
 167.395 +    /**
 167.396 +     * Retrieve the localization resource bundle for this
 167.397 +     * logger for the current default locale.  Note that if
 167.398 +     * the result is null, then the Logger will use a resource
 167.399 +     * bundle inherited from its parent.
 167.400 +     *
 167.401 +     * @return localization bundle (may be null)
 167.402 +     */
 167.403 +//    public ResourceBundle getResourceBundle() {
 167.404 +//        return findResourceBundle(getResourceBundleName());
 167.405 +//    }
 167.406 +
 167.407 +    /**
 167.408 +     * Retrieve the localization resource bundle name for this
 167.409 +     * logger.  Note that if the result is null, then the Logger
 167.410 +     * will use a resource bundle name inherited from its parent.
 167.411 +     *
 167.412 +     * @return localization bundle name (may be null)
 167.413 +     */
 167.414 +    public String getResourceBundleName() {
 167.415 +        return null;
 167.416 +    }
 167.417 +
 167.418 +    /**
 167.419 +     * Set a filter to control output on this Logger.
 167.420 +     * <P>
 167.421 +     * After passing the initial "level" check, the Logger will
 167.422 +     * call this Filter to check if a log record should really
 167.423 +     * be published.
 167.424 +     *
 167.425 +     * @param   newFilter  a filter object (may be null)
 167.426 +     * @exception  SecurityException  if a security manager exists and if
 167.427 +     *             the caller does not have LoggingPermission("control").
 167.428 +     */
 167.429 +//    public void setFilter(Filter newFilter) throws SecurityException {
 167.430 +//        checkAccess();
 167.431 +//    }
 167.432 +
 167.433 +    /**
 167.434 +     * Get the current filter for this Logger.
 167.435 +     *
 167.436 +     * @return  a filter object (may be null)
 167.437 +     */
 167.438 +//    public Filter getFilter() {
 167.439 +//        return filter;
 167.440 +//    }
 167.441 +
 167.442 +    /**
 167.443 +     * Log a LogRecord.
 167.444 +     * <p>
 167.445 +     * All the other logging methods in this class call through
 167.446 +     * this method to actually perform any logging.  Subclasses can
 167.447 +     * override this single method to capture all log activity.
 167.448 +     *
 167.449 +     * @param record the LogRecord to be published
 167.450 +     */
 167.451 +    public void log(LogRecord record) {
 167.452 +        if (record.getLevel().intValue() < levelValue) {
 167.453 +            return;
 167.454 +        }
 167.455 +        
 167.456 +        String method;
 167.457 +        switch (record.getLevel().toString()) {
 167.458 +            case "INFO": method = "info";  break;
 167.459 +            case "SEVERE": method = "error"; break;
 167.460 +            case "WARNING": method = "warn"; break;
 167.461 +            default: method = "log"; break;
 167.462 +        }
 167.463 +
 167.464 +        consoleLog(
 167.465 +            method, 
 167.466 +            record.getLoggerName(),
 167.467 +            record.getMessage()
 167.468 +        );
 167.469 +    }
 167.470 +    
 167.471 +    @JavaScriptBody(args = { "method", "logger", "msg" }, body = 
 167.472 +        "window.console[method]('[' + logger + ']: ' + msg);"
 167.473 +    )
 167.474 +    private static native void consoleLog(
 167.475 +        String method, String logger, String msg
 167.476 +    );
 167.477 +
 167.478 +    // private support method for logging.
 167.479 +    // We fill in the logger name, resource bundle name, and
 167.480 +    // resource bundle and then call "void log(LogRecord)".
 167.481 +    private void doLog(LogRecord lr) {
 167.482 +        doLog(lr, lr.getResourceBundleName());
 167.483 +    }
 167.484 +    private void doLog(LogRecord lr, String bundleName) {
 167.485 +        lr.setLoggerName(name);
 167.486 +        log(lr);
 167.487 +    }
 167.488 +
 167.489 +
 167.490 +    //================================================================
 167.491 +    // Start of convenience methods WITHOUT className and methodName
 167.492 +    //================================================================
 167.493 +
 167.494 +    /**
 167.495 +     * Log a message, with no arguments.
 167.496 +     * <p>
 167.497 +     * If the logger is currently enabled for the given message
 167.498 +     * level then the given message is forwarded to all the
 167.499 +     * registered output Handler objects.
 167.500 +     * <p>
 167.501 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.502 +     * @param   msg     The string message (or a key in the message catalog)
 167.503 +     */
 167.504 +    public void log(Level level, String msg) {
 167.505 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.506 +            return;
 167.507 +        }
 167.508 +        LogRecord lr = new LogRecord(level, msg);
 167.509 +        doLog(lr);
 167.510 +    }
 167.511 +
 167.512 +    /**
 167.513 +     * Log a message, with one object parameter.
 167.514 +     * <p>
 167.515 +     * If the logger is currently enabled for the given message
 167.516 +     * level then a corresponding LogRecord is created and forwarded
 167.517 +     * to all the registered output Handler objects.
 167.518 +     * <p>
 167.519 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.520 +     * @param   msg     The string message (or a key in the message catalog)
 167.521 +     * @param   param1  parameter to the message
 167.522 +     */
 167.523 +    public void log(Level level, String msg, Object param1) {
 167.524 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.525 +            return;
 167.526 +        }
 167.527 +        LogRecord lr = new LogRecord(level, msg);
 167.528 +        Object params[] = { param1 };
 167.529 +        lr.setParameters(params);
 167.530 +        doLog(lr);
 167.531 +    }
 167.532 +
 167.533 +    /**
 167.534 +     * Log a message, with an array of object arguments.
 167.535 +     * <p>
 167.536 +     * If the logger is currently enabled for the given message
 167.537 +     * level then a corresponding LogRecord is created and forwarded
 167.538 +     * to all the registered output Handler objects.
 167.539 +     * <p>
 167.540 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.541 +     * @param   msg     The string message (or a key in the message catalog)
 167.542 +     * @param   params  array of parameters to the message
 167.543 +     */
 167.544 +    public void log(Level level, String msg, Object params[]) {
 167.545 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.546 +            return;
 167.547 +        }
 167.548 +        LogRecord lr = new LogRecord(level, msg);
 167.549 +        lr.setParameters(params);
 167.550 +        doLog(lr);
 167.551 +    }
 167.552 +
 167.553 +    /**
 167.554 +     * Log a message, with associated Throwable information.
 167.555 +     * <p>
 167.556 +     * If the logger is currently enabled for the given message
 167.557 +     * level then the given arguments are stored in a LogRecord
 167.558 +     * which is forwarded to all registered output handlers.
 167.559 +     * <p>
 167.560 +     * Note that the thrown argument is stored in the LogRecord thrown
 167.561 +     * property, rather than the LogRecord parameters property.  Thus is it
 167.562 +     * processed specially by output Formatters and is not treated
 167.563 +     * as a formatting parameter to the LogRecord message property.
 167.564 +     * <p>
 167.565 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.566 +     * @param   msg     The string message (or a key in the message catalog)
 167.567 +     * @param   thrown  Throwable associated with log message.
 167.568 +     */
 167.569 +    public void log(Level level, String msg, Throwable thrown) {
 167.570 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.571 +            return;
 167.572 +        }
 167.573 +        LogRecord lr = new LogRecord(level, msg);
 167.574 +        lr.setThrown(thrown);
 167.575 +        doLog(lr);
 167.576 +    }
 167.577 +
 167.578 +    //================================================================
 167.579 +    // Start of convenience methods WITH className and methodName
 167.580 +    //================================================================
 167.581 +
 167.582 +    /**
 167.583 +     * Log a message, specifying source class and method,
 167.584 +     * with no arguments.
 167.585 +     * <p>
 167.586 +     * If the logger is currently enabled for the given message
 167.587 +     * level then the given message is forwarded to all the
 167.588 +     * registered output Handler objects.
 167.589 +     * <p>
 167.590 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.591 +     * @param   sourceClass    name of class that issued the logging request
 167.592 +     * @param   sourceMethod   name of method that issued the logging request
 167.593 +     * @param   msg     The string message (or a key in the message catalog)
 167.594 +     */
 167.595 +    public void logp(Level level, String sourceClass, String sourceMethod, String msg) {
 167.596 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.597 +            return;
 167.598 +        }
 167.599 +        LogRecord lr = new LogRecord(level, msg);
 167.600 +        lr.setSourceClassName(sourceClass);
 167.601 +        lr.setSourceMethodName(sourceMethod);
 167.602 +        doLog(lr);
 167.603 +    }
 167.604 +
 167.605 +    /**
 167.606 +     * Log a message, specifying source class and method,
 167.607 +     * with a single object parameter to the log message.
 167.608 +     * <p>
 167.609 +     * If the logger is currently enabled for the given message
 167.610 +     * level then a corresponding LogRecord is created and forwarded
 167.611 +     * to all the registered output Handler objects.
 167.612 +     * <p>
 167.613 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.614 +     * @param   sourceClass    name of class that issued the logging request
 167.615 +     * @param   sourceMethod   name of method that issued the logging request
 167.616 +     * @param   msg      The string message (or a key in the message catalog)
 167.617 +     * @param   param1    Parameter to the log message.
 167.618 +     */
 167.619 +    public void logp(Level level, String sourceClass, String sourceMethod,
 167.620 +                                                String msg, Object param1) {
 167.621 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.622 +            return;
 167.623 +        }
 167.624 +        LogRecord lr = new LogRecord(level, msg);
 167.625 +        lr.setSourceClassName(sourceClass);
 167.626 +        lr.setSourceMethodName(sourceMethod);
 167.627 +        Object params[] = { param1 };
 167.628 +        lr.setParameters(params);
 167.629 +        doLog(lr);
 167.630 +    }
 167.631 +
 167.632 +    /**
 167.633 +     * Log a message, specifying source class and method,
 167.634 +     * with an array of object arguments.
 167.635 +     * <p>
 167.636 +     * If the logger is currently enabled for the given message
 167.637 +     * level then a corresponding LogRecord is created and forwarded
 167.638 +     * to all the registered output Handler objects.
 167.639 +     * <p>
 167.640 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.641 +     * @param   sourceClass    name of class that issued the logging request
 167.642 +     * @param   sourceMethod   name of method that issued the logging request
 167.643 +     * @param   msg     The string message (or a key in the message catalog)
 167.644 +     * @param   params  Array of parameters to the message
 167.645 +     */
 167.646 +    public void logp(Level level, String sourceClass, String sourceMethod,
 167.647 +                                                String msg, Object params[]) {
 167.648 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.649 +            return;
 167.650 +        }
 167.651 +        LogRecord lr = new LogRecord(level, msg);
 167.652 +        lr.setSourceClassName(sourceClass);
 167.653 +        lr.setSourceMethodName(sourceMethod);
 167.654 +        lr.setParameters(params);
 167.655 +        doLog(lr);
 167.656 +    }
 167.657 +
 167.658 +    /**
 167.659 +     * Log a message, specifying source class and method,
 167.660 +     * with associated Throwable information.
 167.661 +     * <p>
 167.662 +     * If the logger is currently enabled for the given message
 167.663 +     * level then the given arguments are stored in a LogRecord
 167.664 +     * which is forwarded to all registered output handlers.
 167.665 +     * <p>
 167.666 +     * Note that the thrown argument is stored in the LogRecord thrown
 167.667 +     * property, rather than the LogRecord parameters property.  Thus is it
 167.668 +     * processed specially by output Formatters and is not treated
 167.669 +     * as a formatting parameter to the LogRecord message property.
 167.670 +     * <p>
 167.671 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.672 +     * @param   sourceClass    name of class that issued the logging request
 167.673 +     * @param   sourceMethod   name of method that issued the logging request
 167.674 +     * @param   msg     The string message (or a key in the message catalog)
 167.675 +     * @param   thrown  Throwable associated with log message.
 167.676 +     */
 167.677 +    public void logp(Level level, String sourceClass, String sourceMethod,
 167.678 +                                                        String msg, Throwable thrown) {
 167.679 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.680 +            return;
 167.681 +        }
 167.682 +        LogRecord lr = new LogRecord(level, msg);
 167.683 +        lr.setSourceClassName(sourceClass);
 167.684 +        lr.setSourceMethodName(sourceMethod);
 167.685 +        lr.setThrown(thrown);
 167.686 +        doLog(lr);
 167.687 +    }
 167.688 +
 167.689 +
 167.690 +    //=========================================================================
 167.691 +    // Start of convenience methods WITH className, methodName and bundle name.
 167.692 +    //=========================================================================
 167.693 +
 167.694 +
 167.695 +    /**
 167.696 +     * Log a message, specifying source class, method, and resource bundle name
 167.697 +     * with no arguments.
 167.698 +     * <p>
 167.699 +     * If the logger is currently enabled for the given message
 167.700 +     * level then the given message is forwarded to all the
 167.701 +     * registered output Handler objects.
 167.702 +     * <p>
 167.703 +     * The msg string is localized using the named resource bundle.  If the
 167.704 +     * resource bundle name is null, or an empty String or invalid
 167.705 +     * then the msg string is not localized.
 167.706 +     * <p>
 167.707 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.708 +     * @param   sourceClass    name of class that issued the logging request
 167.709 +     * @param   sourceMethod   name of method that issued the logging request
 167.710 +     * @param   bundleName     name of resource bundle to localize msg,
 167.711 +     *                         can be null
 167.712 +     * @param   msg     The string message (or a key in the message catalog)
 167.713 +     */
 167.714 +
 167.715 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 167.716 +                                String bundleName, String msg) {
 167.717 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.718 +            return;
 167.719 +        }
 167.720 +        LogRecord lr = new LogRecord(level, msg);
 167.721 +        lr.setSourceClassName(sourceClass);
 167.722 +        lr.setSourceMethodName(sourceMethod);
 167.723 +        doLog(lr, bundleName);
 167.724 +    }
 167.725 +
 167.726 +    /**
 167.727 +     * Log a message, specifying source class, method, and resource bundle name,
 167.728 +     * with a single object parameter to the log message.
 167.729 +     * <p>
 167.730 +     * If the logger is currently enabled for the given message
 167.731 +     * level then a corresponding LogRecord is created and forwarded
 167.732 +     * to all the registered output Handler objects.
 167.733 +     * <p>
 167.734 +     * The msg string is localized using the named resource bundle.  If the
 167.735 +     * resource bundle name is null, or an empty String or invalid
 167.736 +     * then the msg string is not localized.
 167.737 +     * <p>
 167.738 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.739 +     * @param   sourceClass    name of class that issued the logging request
 167.740 +     * @param   sourceMethod   name of method that issued the logging request
 167.741 +     * @param   bundleName     name of resource bundle to localize msg,
 167.742 +     *                         can be null
 167.743 +     * @param   msg      The string message (or a key in the message catalog)
 167.744 +     * @param   param1    Parameter to the log message.
 167.745 +     */
 167.746 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 167.747 +                                String bundleName, String msg, Object param1) {
 167.748 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.749 +            return;
 167.750 +        }
 167.751 +        LogRecord lr = new LogRecord(level, msg);
 167.752 +        lr.setSourceClassName(sourceClass);
 167.753 +        lr.setSourceMethodName(sourceMethod);
 167.754 +        Object params[] = { param1 };
 167.755 +        lr.setParameters(params);
 167.756 +        doLog(lr, bundleName);
 167.757 +    }
 167.758 +
 167.759 +    /**
 167.760 +     * Log a message, specifying source class, method, and resource bundle name,
 167.761 +     * with an array of object arguments.
 167.762 +     * <p>
 167.763 +     * If the logger is currently enabled for the given message
 167.764 +     * level then a corresponding LogRecord is created and forwarded
 167.765 +     * to all the registered output Handler objects.
 167.766 +     * <p>
 167.767 +     * The msg string is localized using the named resource bundle.  If the
 167.768 +     * resource bundle name is null, or an empty String or invalid
 167.769 +     * then the msg string is not localized.
 167.770 +     * <p>
 167.771 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.772 +     * @param   sourceClass    name of class that issued the logging request
 167.773 +     * @param   sourceMethod   name of method that issued the logging request
 167.774 +     * @param   bundleName     name of resource bundle to localize msg,
 167.775 +     *                         can be null.
 167.776 +     * @param   msg     The string message (or a key in the message catalog)
 167.777 +     * @param   params  Array of parameters to the message
 167.778 +     */
 167.779 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 167.780 +                                String bundleName, String msg, Object params[]) {
 167.781 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.782 +            return;
 167.783 +        }
 167.784 +        LogRecord lr = new LogRecord(level, msg);
 167.785 +        lr.setSourceClassName(sourceClass);
 167.786 +        lr.setSourceMethodName(sourceMethod);
 167.787 +        lr.setParameters(params);
 167.788 +        doLog(lr, bundleName);
 167.789 +    }
 167.790 +
 167.791 +    /**
 167.792 +     * Log a message, specifying source class, method, and resource bundle name,
 167.793 +     * with associated Throwable information.
 167.794 +     * <p>
 167.795 +     * If the logger is currently enabled for the given message
 167.796 +     * level then the given arguments are stored in a LogRecord
 167.797 +     * which is forwarded to all registered output handlers.
 167.798 +     * <p>
 167.799 +     * The msg string is localized using the named resource bundle.  If the
 167.800 +     * resource bundle name is null, or an empty String or invalid
 167.801 +     * then the msg string is not localized.
 167.802 +     * <p>
 167.803 +     * Note that the thrown argument is stored in the LogRecord thrown
 167.804 +     * property, rather than the LogRecord parameters property.  Thus is it
 167.805 +     * processed specially by output Formatters and is not treated
 167.806 +     * as a formatting parameter to the LogRecord message property.
 167.807 +     * <p>
 167.808 +     * @param   level   One of the message level identifiers, e.g., SEVERE
 167.809 +     * @param   sourceClass    name of class that issued the logging request
 167.810 +     * @param   sourceMethod   name of method that issued the logging request
 167.811 +     * @param   bundleName     name of resource bundle to localize msg,
 167.812 +     *                         can be null
 167.813 +     * @param   msg     The string message (or a key in the message catalog)
 167.814 +     * @param   thrown  Throwable associated with log message.
 167.815 +     */
 167.816 +    public void logrb(Level level, String sourceClass, String sourceMethod,
 167.817 +                                        String bundleName, String msg, Throwable thrown) {
 167.818 +        if (level.intValue() < levelValue || levelValue == offValue) {
 167.819 +            return;
 167.820 +        }
 167.821 +        LogRecord lr = new LogRecord(level, msg);
 167.822 +        lr.setSourceClassName(sourceClass);
 167.823 +        lr.setSourceMethodName(sourceMethod);
 167.824 +        lr.setThrown(thrown);
 167.825 +        doLog(lr, bundleName);
 167.826 +    }
 167.827 +
 167.828 +
 167.829 +    //======================================================================
 167.830 +    // Start of convenience methods for logging method entries and returns.
 167.831 +    //======================================================================
 167.832 +
 167.833 +    /**
 167.834 +     * Log a method entry.
 167.835 +     * <p>
 167.836 +     * This is a convenience method that can be used to log entry
 167.837 +     * to a method.  A LogRecord with message "ENTRY", log level
 167.838 +     * FINER, and the given sourceMethod and sourceClass is logged.
 167.839 +     * <p>
 167.840 +     * @param   sourceClass    name of class that issued the logging request
 167.841 +     * @param   sourceMethod   name of method that is being entered
 167.842 +     */
 167.843 +    public void entering(String sourceClass, String sourceMethod) {
 167.844 +        if (Level.FINER.intValue() < levelValue) {
 167.845 +            return;
 167.846 +        }
 167.847 +        logp(Level.FINER, sourceClass, sourceMethod, "ENTRY");
 167.848 +    }
 167.849 +
 167.850 +    /**
 167.851 +     * Log a method entry, with one parameter.
 167.852 +     * <p>
 167.853 +     * This is a convenience method that can be used to log entry
 167.854 +     * to a method.  A LogRecord with message "ENTRY {0}", log level
 167.855 +     * FINER, and the given sourceMethod, sourceClass, and parameter
 167.856 +     * is logged.
 167.857 +     * <p>
 167.858 +     * @param   sourceClass    name of class that issued the logging request
 167.859 +     * @param   sourceMethod   name of method that is being entered
 167.860 +     * @param   param1         parameter to the method being entered
 167.861 +     */
 167.862 +    public void entering(String sourceClass, String sourceMethod, Object param1) {
 167.863 +        if (Level.FINER.intValue() < levelValue) {
 167.864 +            return;
 167.865 +        }
 167.866 +        Object params[] = { param1 };
 167.867 +        logp(Level.FINER, sourceClass, sourceMethod, "ENTRY {0}", params);
 167.868 +    }
 167.869 +
 167.870 +    /**
 167.871 +     * Log a method entry, with an array of parameters.
 167.872 +     * <p>
 167.873 +     * This is a convenience method that can be used to log entry
 167.874 +     * to a method.  A LogRecord with message "ENTRY" (followed by a
 167.875 +     * format {N} indicator for each entry in the parameter array),
 167.876 +     * log level FINER, and the given sourceMethod, sourceClass, and
 167.877 +     * parameters is logged.
 167.878 +     * <p>
 167.879 +     * @param   sourceClass    name of class that issued the logging request
 167.880 +     * @param   sourceMethod   name of method that is being entered
 167.881 +     * @param   params         array of parameters to the method being entered
 167.882 +     */
 167.883 +    public void entering(String sourceClass, String sourceMethod, Object params[]) {
 167.884 +        if (Level.FINER.intValue() < levelValue) {
 167.885 +            return;
 167.886 +        }
 167.887 +        String msg = "ENTRY";
 167.888 +        if (params == null ) {
 167.889 +           logp(Level.FINER, sourceClass, sourceMethod, msg);
 167.890 +           return;
 167.891 +        }
 167.892 +        for (int i = 0; i < params.length; i++) {
 167.893 +            msg = msg + " {" + i + "}";
 167.894 +        }
 167.895 +        logp(Level.FINER, sourceClass, sourceMethod, msg, params);
 167.896 +    }
 167.897 +
 167.898 +    /**
 167.899 +     * Log a method return.
 167.900 +     * <p>
 167.901 +     * This is a convenience method that can be used to log returning
 167.902 +     * from a method.  A LogRecord with message "RETURN", log level
 167.903 +     * FINER, and the given sourceMethod and sourceClass is logged.
 167.904 +     * <p>
 167.905 +     * @param   sourceClass    name of class that issued the logging request
 167.906 +     * @param   sourceMethod   name of the method
 167.907 +     */
 167.908 +    public void exiting(String sourceClass, String sourceMethod) {
 167.909 +        if (Level.FINER.intValue() < levelValue) {
 167.910 +            return;
 167.911 +        }
 167.912 +        logp(Level.FINER, sourceClass, sourceMethod, "RETURN");
 167.913 +    }
 167.914 +
 167.915 +
 167.916 +    /**
 167.917 +     * Log a method return, with result object.
 167.918 +     * <p>
 167.919 +     * This is a convenience method that can be used to log returning
 167.920 +     * from a method.  A LogRecord with message "RETURN {0}", log level
 167.921 +     * FINER, and the gives sourceMethod, sourceClass, and result
 167.922 +     * object is logged.
 167.923 +     * <p>
 167.924 +     * @param   sourceClass    name of class that issued the logging request
 167.925 +     * @param   sourceMethod   name of the method
 167.926 +     * @param   result  Object that is being returned
 167.927 +     */
 167.928 +    public void exiting(String sourceClass, String sourceMethod, Object result) {
 167.929 +        if (Level.FINER.intValue() < levelValue) {
 167.930 +            return;
 167.931 +        }
 167.932 +        Object params[] = { result };
 167.933 +        logp(Level.FINER, sourceClass, sourceMethod, "RETURN {0}", result);
 167.934 +    }
 167.935 +
 167.936 +    /**
 167.937 +     * Log throwing an exception.
 167.938 +     * <p>
 167.939 +     * This is a convenience method to log that a method is
 167.940 +     * terminating by throwing an exception.  The logging is done
 167.941 +     * using the FINER level.
 167.942 +     * <p>
 167.943 +     * If the logger is currently enabled for the given message
 167.944 +     * level then the given arguments are stored in a LogRecord
 167.945 +     * which is forwarded to all registered output handlers.  The
 167.946 +     * LogRecord's message is set to "THROW".
 167.947 +     * <p>
 167.948 +     * Note that the thrown argument is stored in the LogRecord thrown
 167.949 +     * property, rather than the LogRecord parameters property.  Thus is it
 167.950 +     * processed specially by output Formatters and is not treated
 167.951 +     * as a formatting parameter to the LogRecord message property.
 167.952 +     * <p>
 167.953 +     * @param   sourceClass    name of class that issued the logging request
 167.954 +     * @param   sourceMethod  name of the method.
 167.955 +     * @param   thrown  The Throwable that is being thrown.
 167.956 +     */
 167.957 +    public void throwing(String sourceClass, String sourceMethod, Throwable thrown) {
 167.958 +        if (Level.FINER.intValue() < levelValue || levelValue == offValue ) {
 167.959 +            return;
 167.960 +        }
 167.961 +        LogRecord lr = new LogRecord(Level.FINER, "THROW");
 167.962 +        lr.setSourceClassName(sourceClass);
 167.963 +        lr.setSourceMethodName(sourceMethod);
 167.964 +        lr.setThrown(thrown);
 167.965 +        doLog(lr);
 167.966 +    }
 167.967 +
 167.968 +    //=======================================================================
 167.969 +    // Start of simple convenience methods using level names as method names
 167.970 +    //=======================================================================
 167.971 +
 167.972 +    /**
 167.973 +     * Log a SEVERE message.
 167.974 +     * <p>
 167.975 +     * If the logger is currently enabled for the SEVERE message
 167.976 +     * level then the given message is forwarded to all the
 167.977 +     * registered output Handler objects.
 167.978 +     * <p>
 167.979 +     * @param   msg     The string message (or a key in the message catalog)
 167.980 +     */
 167.981 +    public void severe(String msg) {
 167.982 +        if (Level.SEVERE.intValue() < levelValue) {
 167.983 +            return;
 167.984 +        }
 167.985 +        log(Level.SEVERE, msg);
 167.986 +    }
 167.987 +
 167.988 +    /**
 167.989 +     * Log a WARNING message.
 167.990 +     * <p>
 167.991 +     * If the logger is currently enabled for the WARNING message
 167.992 +     * level then the given message is forwarded to all the
 167.993 +     * registered output Handler objects.
 167.994 +     * <p>
 167.995 +     * @param   msg     The string message (or a key in the message catalog)
 167.996 +     */
 167.997 +    public void warning(String msg) {
 167.998 +        if (Level.WARNING.intValue() < levelValue) {
 167.999 +            return;
167.1000 +        }
167.1001 +        log(Level.WARNING, msg);
167.1002 +    }
167.1003 +
167.1004 +    /**
167.1005 +     * Log an INFO message.
167.1006 +     * <p>
167.1007 +     * If the logger is currently enabled for the INFO message
167.1008 +     * level then the given message is forwarded to all the
167.1009 +     * registered output Handler objects.
167.1010 +     * <p>
167.1011 +     * @param   msg     The string message (or a key in the message catalog)
167.1012 +     */
167.1013 +    public void info(String msg) {
167.1014 +        if (Level.INFO.intValue() < levelValue) {
167.1015 +            return;
167.1016 +        }
167.1017 +        log(Level.INFO, msg);
167.1018 +    }
167.1019 +
167.1020 +    /**
167.1021 +     * Log a CONFIG message.
167.1022 +     * <p>
167.1023 +     * If the logger is currently enabled for the CONFIG message
167.1024 +     * level then the given message is forwarded to all the
167.1025 +     * registered output Handler objects.
167.1026 +     * <p>
167.1027 +     * @param   msg     The string message (or a key in the message catalog)
167.1028 +     */
167.1029 +    public void config(String msg) {
167.1030 +        if (Level.CONFIG.intValue() < levelValue) {
167.1031 +            return;
167.1032 +        }
167.1033 +        log(Level.CONFIG, msg);
167.1034 +    }
167.1035 +
167.1036 +    /**
167.1037 +     * Log a FINE message.
167.1038 +     * <p>
167.1039 +     * If the logger is currently enabled for the FINE message
167.1040 +     * level then the given message is forwarded to all the
167.1041 +     * registered output Handler objects.
167.1042 +     * <p>
167.1043 +     * @param   msg     The string message (or a key in the message catalog)
167.1044 +     */
167.1045 +    public void fine(String msg) {
167.1046 +        if (Level.FINE.intValue() < levelValue) {
167.1047 +            return;
167.1048 +        }
167.1049 +        log(Level.FINE, msg);
167.1050 +    }
167.1051 +
167.1052 +    /**
167.1053 +     * Log a FINER message.
167.1054 +     * <p>
167.1055 +     * If the logger is currently enabled for the FINER message
167.1056 +     * level then the given message is forwarded to all the
167.1057 +     * registered output Handler objects.
167.1058 +     * <p>
167.1059 +     * @param   msg     The string message (or a key in the message catalog)
167.1060 +     */
167.1061 +    public void finer(String msg) {
167.1062 +        if (Level.FINER.intValue() < levelValue) {
167.1063 +            return;
167.1064 +        }
167.1065 +        log(Level.FINER, msg);
167.1066 +    }
167.1067 +
167.1068 +    /**
167.1069 +     * Log a FINEST message.
167.1070 +     * <p>
167.1071 +     * If the logger is currently enabled for the FINEST message
167.1072 +     * level then the given message is forwarded to all the
167.1073 +     * registered output Handler objects.
167.1074 +     * <p>
167.1075 +     * @param   msg     The string message (or a key in the message catalog)
167.1076 +     */
167.1077 +    public void finest(String msg) {
167.1078 +        if (Level.FINEST.intValue() < levelValue) {
167.1079 +            return;
167.1080 +        }
167.1081 +        log(Level.FINEST, msg);
167.1082 +    }
167.1083 +
167.1084 +    //================================================================
167.1085 +    // End of convenience methods
167.1086 +    //================================================================
167.1087 +
167.1088 +    /**
167.1089 +     * Set the log level specifying which message levels will be
167.1090 +     * logged by this logger.  Message levels lower than this
167.1091 +     * value will be discarded.  The level value Level.OFF
167.1092 +     * can be used to turn off logging.
167.1093 +     * <p>
167.1094 +     * If the new level is null, it means that this node should
167.1095 +     * inherit its level from its nearest ancestor with a specific
167.1096 +     * (non-null) level value.
167.1097 +     *
167.1098 +     * @param newLevel   the new value for the log level (may be null)
167.1099 +     * @exception  SecurityException  if a security manager exists and if
167.1100 +     *             the caller does not have LoggingPermission("control").
167.1101 +     */
167.1102 +    public void setLevel(Level newLevel) throws SecurityException {
167.1103 +        levelValue = newLevel.intValue();
167.1104 +        levelObject = newLevel;
167.1105 +    }
167.1106 +
167.1107 +    /**
167.1108 +     * Get the log Level that has been specified for this Logger.
167.1109 +     * The result may be null, which means that this logger's
167.1110 +     * effective level will be inherited from its parent.
167.1111 +     *
167.1112 +     * @return  this Logger's level
167.1113 +     */
167.1114 +    public Level getLevel() {
167.1115 +        return levelObject;
167.1116 +    }
167.1117 +
167.1118 +    /**
167.1119 +     * Check if a message of the given level would actually be logged
167.1120 +     * by this logger.  This check is based on the Loggers effective level,
167.1121 +     * which may be inherited from its parent.
167.1122 +     *
167.1123 +     * @param   level   a message logging level
167.1124 +     * @return  true if the given message level is currently being logged.
167.1125 +     */
167.1126 +    public boolean isLoggable(Level level) {
167.1127 +        if (level.intValue() < levelValue || levelValue == offValue) {
167.1128 +            return false;
167.1129 +        }
167.1130 +        return true;
167.1131 +    }
167.1132 +
167.1133 +    /**
167.1134 +     * Get the name for this logger.
167.1135 +     * @return logger name.  Will be null for anonymous Loggers.
167.1136 +     */
167.1137 +    public String getName() {
167.1138 +        return name;
167.1139 +    }
167.1140 +
167.1141 +    /**
167.1142 +     * Add a log Handler to receive logging messages.
167.1143 +     * <p>
167.1144 +     * By default, Loggers also send their output to their parent logger.
167.1145 +     * Typically the root Logger is configured with a set of Handlers
167.1146 +     * that essentially act as default handlers for all loggers.
167.1147 +     *
167.1148 +     * @param   handler a logging Handler
167.1149 +     * @exception  SecurityException  if a security manager exists and if
167.1150 +     *             the caller does not have LoggingPermission("control").
167.1151 +     */
167.1152 +//    public void addHandler(Handler handler) throws SecurityException {
167.1153 +//        // Check for null handler
167.1154 +//        handler.getClass();
167.1155 +//        checkAccess();
167.1156 +//        handlers.add(handler);
167.1157 +//    }
167.1158 +
167.1159 +    /**
167.1160 +     * Remove a log Handler.
167.1161 +     * <P>
167.1162 +     * Returns silently if the given Handler is not found or is null
167.1163 +     *
167.1164 +     * @param   handler a logging Handler
167.1165 +     * @exception  SecurityException  if a security manager exists and if
167.1166 +     *             the caller does not have LoggingPermission("control").
167.1167 +     */
167.1168 +//    public void removeHandler(Handler handler) throws SecurityException {
167.1169 +//        checkAccess();
167.1170 +//        if (handler == null) {
167.1171 +//            return;
167.1172 +//        }
167.1173 +//        handlers.remove(handler);
167.1174 +//    }
167.1175 +
167.1176 +    /**
167.1177 +     * Get the Handlers associated with this logger.
167.1178 +     * <p>
167.1179 +     * @return  an array of all registered Handlers
167.1180 +     */
167.1181 +//    public Handler[] getHandlers() {
167.1182 +//        return handlers.toArray(emptyHandlers);
167.1183 +//    }
167.1184 +
167.1185 +    /**
167.1186 +     * Specify whether or not this logger should send its output
167.1187 +     * to its parent Logger.  This means that any LogRecords will
167.1188 +     * also be written to the parent's Handlers, and potentially
167.1189 +     * to its parent, recursively up the namespace.
167.1190 +     *
167.1191 +     * @param useParentHandlers   true if output is to be sent to the
167.1192 +     *          logger's parent.
167.1193 +     * @exception  SecurityException  if a security manager exists and if
167.1194 +     *             the caller does not have LoggingPermission("control").
167.1195 +     */
167.1196 +    public void setUseParentHandlers(boolean useParentHandlers) {
167.1197 +        checkAccess();
167.1198 +    }
167.1199 +
167.1200 +    /**
167.1201 +     * Discover whether or not this logger is sending its output
167.1202 +     * to its parent logger.
167.1203 +     *
167.1204 +     * @return  true if output is to be sent to the logger's parent
167.1205 +     */
167.1206 +    public boolean getUseParentHandlers() {
167.1207 +        return true;
167.1208 +    }
167.1209 +
167.1210 +    /**
167.1211 +     * Return the parent for this Logger.
167.1212 +     * <p>
167.1213 +     * This method returns the nearest extant parent in the namespace.
167.1214 +     * Thus if a Logger is called "a.b.c.d", and a Logger called "a.b"
167.1215 +     * has been created but no logger "a.b.c" exists, then a call of
167.1216 +     * getParent on the Logger "a.b.c.d" will return the Logger "a.b".
167.1217 +     * <p>
167.1218 +     * The result will be null if it is called on the root Logger
167.1219 +     * in the namespace.
167.1220 +     *
167.1221 +     * @return nearest existing parent Logger
167.1222 +     */
167.1223 +    public Logger getParent() {
167.1224 +        // Note: this used to be synchronized on treeLock.  However, this only
167.1225 +        // provided memory semantics, as there was no guarantee that the caller
167.1226 +        // would synchronize on treeLock (in fact, there is no way for external
167.1227 +        // callers to so synchronize).  Therefore, we have made parent volatile
167.1228 +        // instead.
167.1229 +        String n = getName();
167.1230 +        int at = n.length();
167.1231 +        for (;;) {
167.1232 +            int last = n.lastIndexOf('.', at - 1);
167.1233 +            if (last == -1) {
167.1234 +                return getGlobal();
167.1235 +            }
167.1236 +            Logger p = ALL.get(n.substring(0, last));
167.1237 +            if (p != null) {
167.1238 +                return p;
167.1239 +            }
167.1240 +            at = last;
167.1241 +        }
167.1242 +    }
167.1243 +
167.1244 +    /**
167.1245 +     * Set the parent for this Logger.  This method is used by
167.1246 +     * the LogManager to update a Logger when the namespace changes.
167.1247 +     * <p>
167.1248 +     * It should not be called from application code.
167.1249 +     * <p>
167.1250 +     * @param  parent   the new parent logger
167.1251 +     * @exception  SecurityException  if a security manager exists and if
167.1252 +     *             the caller does not have LoggingPermission("control").
167.1253 +     */
167.1254 +    public void setParent(Logger parent) {
167.1255 +        if (parent == null) {
167.1256 +            throw new NullPointerException();
167.1257 +        }
167.1258 +        checkAccess();
167.1259 +    }
167.1260 +
167.1261 +}
   168.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ReaderTest.java	Wed Feb 27 17:50:47 2013 +0100
   168.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ReaderTest.java	Mon Oct 07 14:20:58 2013 +0200
   168.3 @@ -18,8 +18,10 @@
   168.4  package org.apidesign.bck2brwsr.compact.tck;
   168.5  
   168.6  import java.io.ByteArrayInputStream;
   168.7 +import java.io.ByteArrayOutputStream;
   168.8  import java.io.IOException;
   168.9  import java.io.InputStreamReader;
  168.10 +import java.io.OutputStreamWriter;
  168.11  import java.io.UnsupportedEncodingException;
  168.12  import java.util.Arrays;
  168.13  import org.apidesign.bck2brwsr.vmtest.Compare;
  168.14 @@ -40,7 +42,10 @@
  168.15          };
  168.16          ByteArrayInputStream is = new ByteArrayInputStream(arr);
  168.17          InputStreamReader r = new InputStreamReader(is, "UTF-8");
  168.18 -        
  168.19 +        return readReader(r);        
  168.20 +    }
  168.21 +
  168.22 +    private String readReader(InputStreamReader r) throws IOException {
  168.23          StringBuilder sb = new StringBuilder();
  168.24          for (;;) {
  168.25              int ch = r.read();
  168.26 @@ -52,7 +57,19 @@
  168.27          return sb.toString().toString();
  168.28      }
  168.29      @Compare public String stringToBytes() throws UnsupportedEncodingException {
  168.30 -        return Arrays.toString("\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("UTF-8"));
  168.31 +        return Arrays.toString(YellowHorse.getBytes("UTF-8"));
  168.32 +    }
  168.33 +    private final String YellowHorse = "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148";
  168.34 +    
  168.35 +    @Compare public String readAndWrite() throws Exception {
  168.36 +        ByteArrayOutputStream arr = new ByteArrayOutputStream();
  168.37 +        OutputStreamWriter w = new OutputStreamWriter(arr);
  168.38 +        w.write(YellowHorse);
  168.39 +        w.close();
  168.40 +        
  168.41 +        ByteArrayInputStream is = new ByteArrayInputStream(arr.toByteArray());
  168.42 +        InputStreamReader r = new InputStreamReader(is, "UTF-8");
  168.43 +        return readReader(r);
  168.44      }
  168.45      
  168.46      @Factory public static Object[] create() {
   169.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java	Wed Feb 27 17:50:47 2013 +0100
   169.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipCompatibilityTest.java	Mon Oct 07 14:20:58 2013 +0200
   169.3 @@ -30,9 +30,10 @@
   169.4  public class ZipCompatibilityTest {
   169.5      @Compare
   169.6      public String testDemoStaticCalculator() throws IOException {
   169.7 -        InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
   169.8 +        InputStream is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
   169.9          ZipArchive zip = ZipArchive.createZip(is);
  169.10 -        return zip.toString();
  169.11 +        final String ts = zip.toString();
  169.12 +        return ts.substring(0, 4096) + ts.hashCode();
  169.13      }
  169.14      
  169.15      @Factory
   170.1 --- a/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java	Wed Feb 27 17:50:47 2013 +0100
   170.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/compact/tck/ZipVsJzLibTest.java	Mon Oct 07 14:20:58 2013 +0200
   170.3 @@ -27,10 +27,10 @@
   170.4   */
   170.5  public class ZipVsJzLibTest {
   170.6      @Test public void r() throws IOException {
   170.7 -        InputStream is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
   170.8 +        InputStream is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
   170.9          ZipArchive zip = ZipArchive.createZip(is);
  170.10          
  170.11 -        is = getClass().getResourceAsStream("demo.static.calculator-0.3-SNAPSHOT.jar");
  170.12 +        is = getClass().getResourceAsStream("demo.static.calculator-TEST.jar");
  170.13          ZipArchive real = ZipArchive.createReal(is);
  170.14          
  170.15          real.assertEquals(zip, "Are they the same?");
   171.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   171.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java	Mon Oct 07 14:20:58 2013 +0200
   171.3 @@ -0,0 +1,43 @@
   171.4 +/**
   171.5 + * Back 2 Browser Bytecode Translator
   171.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   171.7 + *
   171.8 + * This program is free software: you can redistribute it and/or modify
   171.9 + * it under the terms of the GNU General Public License as published by
  171.10 + * the Free Software Foundation, version 2 of the License.
  171.11 + *
  171.12 + * This program is distributed in the hope that it will be useful,
  171.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  171.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  171.15 + * GNU General Public License for more details.
  171.16 + *
  171.17 + * You should have received a copy of the GNU General Public License
  171.18 + * along with this program. Look for COPYING file in the top folder.
  171.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  171.20 + */
  171.21 +package org.apidesign.bck2brwsr.tck;
  171.22 +
  171.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  171.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  171.25 +import org.testng.annotations.Factory;
  171.26 +
  171.27 +/**
  171.28 + *
  171.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  171.30 + */
  171.31 +public class AssertionTest {
  171.32 +
  171.33 +    @Compare public Object checkAssert() throws ClassNotFoundException {
  171.34 +        try {
  171.35 +            assert false : "Is assertion status on?";
  171.36 +            return null;
  171.37 +        } catch (AssertionError ex) {
  171.38 +            return ex.getClass().getName();
  171.39 +        }
  171.40 +    }
  171.41 +    
  171.42 +    @Factory
  171.43 +    public static Object[] create() {
  171.44 +        return VMTest.create(AssertionTest.class);
  171.45 +    }
  171.46 +}
   172.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   172.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java	Mon Oct 07 14:20:58 2013 +0200
   172.3 @@ -0,0 +1,57 @@
   172.4 +/**
   172.5 + * Back 2 Browser Bytecode Translator
   172.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   172.7 + *
   172.8 + * This program is free software: you can redistribute it and/or modify
   172.9 + * it under the terms of the GNU General Public License as published by
  172.10 + * the Free Software Foundation, version 2 of the License.
  172.11 + *
  172.12 + * This program is distributed in the hope that it will be useful,
  172.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  172.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  172.15 + * GNU General Public License for more details.
  172.16 + *
  172.17 + * You should have received a copy of the GNU General Public License
  172.18 + * along with this program. Look for COPYING file in the top folder.
  172.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  172.20 + */
  172.21 +package org.apidesign.bck2brwsr.tck;
  172.22 +
  172.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  172.24 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  172.25 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
  172.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  172.27 +import org.testng.annotations.Factory;
  172.28 +
  172.29 +/**
  172.30 + *
  172.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  172.32 + */
  172.33 +public class BrwsrCheckTest {
  172.34 +
  172.35 +    @BrwsrTest public void assertWindowObjectIsDefined() {
  172.36 +        assert window() != null : "No window object found!";
  172.37 +    }
  172.38 +
  172.39 +    
  172.40 +    
  172.41 +    
  172.42 +    @HtmlFragment("<h1 id='hello'>\n"
  172.43 +        + "Hello!\n"
  172.44 +        + "</h1>\n")
  172.45 +    @BrwsrTest public void accessProvidedFragment() {
  172.46 +        assert getElementById("hello") != null : "Element with 'hello' ID found";
  172.47 +    }
  172.48 +    
  172.49 +    @Factory
  172.50 +    public static Object[] create() {
  172.51 +        return VMTest.create(BrwsrCheckTest.class);
  172.52 +    }
  172.53 +    
  172.54 +
  172.55 +    @JavaScriptBody(args = {}, body = "return window;")
  172.56 +    private static native Object window();
  172.57 +
  172.58 +    @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);")
  172.59 +    private static native Object getElementById(String id);
  172.60 +}
   173.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   173.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java	Mon Oct 07 14:20:58 2013 +0200
   173.3 @@ -0,0 +1,147 @@
   173.4 +/**
   173.5 + * Back 2 Browser Bytecode Translator
   173.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   173.7 + *
   173.8 + * This program is free software: you can redistribute it and/or modify
   173.9 + * it under the terms of the GNU General Public License as published by
  173.10 + * the Free Software Foundation, version 2 of the License.
  173.11 + *
  173.12 + * This program is distributed in the hope that it will be useful,
  173.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  173.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  173.15 + * GNU General Public License for more details.
  173.16 + *
  173.17 + * You should have received a copy of the GNU General Public License
  173.18 + * along with this program. Look for COPYING file in the top folder.
  173.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  173.20 + */
  173.21 +package org.apidesign.bck2brwsr.tck;
  173.22 +
  173.23 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  173.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  173.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  173.26 +import org.testng.annotations.Factory;
  173.27 +
  173.28 +/**
  173.29 + *
  173.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  173.31 + */
  173.32 +public class ByteArithmeticTest {
  173.33 +    
  173.34 +    private static byte add(byte x, byte y) {
  173.35 +        return (byte)(x + y);
  173.36 +    }
  173.37 +    
  173.38 +    private static byte sub(byte x, byte y) {
  173.39 +        return (byte)(x - y);
  173.40 +    }
  173.41 +    
  173.42 +    private static byte mul(byte x, byte y) {
  173.43 +        return (byte)(x * y);
  173.44 +    }
  173.45 +    
  173.46 +    private static byte div(byte x, byte y) {
  173.47 +        return (byte)(x / y);
  173.48 +    }
  173.49 +    
  173.50 +    private static byte mod(byte x, byte y) {
  173.51 +        return (byte)(x % y);
  173.52 +    }
  173.53 +    
  173.54 +    @Compare public byte conversion() {
  173.55 +        return (byte)123456;
  173.56 +    }
  173.57 +    
  173.58 +    @Compare public byte addOverflow() {
  173.59 +        return add(Byte.MAX_VALUE, (byte)1);
  173.60 +    }
  173.61 +    
  173.62 +    @Compare public byte subUnderflow() {
  173.63 +        return sub(Byte.MIN_VALUE, (byte)1);
  173.64 +    }
  173.65 +    
  173.66 +    @Compare public byte addMaxByteAndMaxByte() {
  173.67 +        return add(Byte.MAX_VALUE, Byte.MAX_VALUE);
  173.68 +    }
  173.69 +    
  173.70 +    @Compare public byte subMinByteAndMinByte() {
  173.71 +        return sub(Byte.MIN_VALUE, Byte.MIN_VALUE);
  173.72 +    }
  173.73 +    
  173.74 +    @Compare public byte multiplyMaxByte() {
  173.75 +        return mul(Byte.MAX_VALUE, (byte)2);
  173.76 +    }
  173.77 +    
  173.78 +    @Compare public byte multiplyMaxByteAndMaxByte() {
  173.79 +        return mul(Byte.MAX_VALUE, Byte.MAX_VALUE);
  173.80 +    }
  173.81 +    
  173.82 +    @Compare public byte multiplyMinByte() {
  173.83 +        return mul(Byte.MIN_VALUE, (byte)2);
  173.84 +    }
  173.85 +    
  173.86 +    @Compare public byte multiplyMinByteAndMinByte() {
  173.87 +        return mul(Byte.MIN_VALUE, Byte.MIN_VALUE);
  173.88 +    }
  173.89 +    
  173.90 +    @Compare public byte multiplyPrecision() {
  173.91 +        return mul((byte)17638, (byte)1103);
  173.92 +    }
  173.93 +    
  173.94 +    @Compare public byte division() {
  173.95 +        return div((byte)1, (byte)2);
  173.96 +    }
  173.97 +    
  173.98 +    @Compare public byte divisionReminder() {
  173.99 +        return mod((byte)1, (byte)2);
 173.100 +    }
 173.101 +
 173.102 +    private static int readShort(byte[] byteCodes, int offset) {
 173.103 +        int signed = byteCodes[offset];
 173.104 +        byte b0 = (byte)signed;
 173.105 +        return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
 173.106 +    }
 173.107 +    
 173.108 +    private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
 173.109 +        return readShort(byteCodes, offsetInstruction + 1);
 173.110 +    }
 173.111 +    
 173.112 +    @Compare public int readIntArgs255and156() {
 173.113 +        final byte[] arr = new byte[] { (byte)0, (byte)255, (byte)156 };
 173.114 +        
 173.115 +        assert arr[1] == -1 : "First byte: " + arr[1];
 173.116 +        assert arr[2] == -100 : "Second byte: " + arr[2];
 173.117 +        final int ret = readShortArg(arr, 0);
 173.118 +        assert ret < 65000: "Value: " + ret;
 173.119 +        return ret;
 173.120 +    }
 173.121 +    
 173.122 +    @JavaScriptBody(args = { "arr" }, body = "arr[1] = 255; arr[2] = 156; return arr;")
 173.123 +    private static byte[] fill255and156(byte[] arr) {
 173.124 +        arr[1] = (byte)255;
 173.125 +        arr[2] = (byte)156;
 173.126 +        return arr;
 173.127 +    }
 173.128 +
 173.129 +    @Compare public int readIntArgs255and156JSArray() {
 173.130 +        final byte[] arr = fill255and156(new byte[] { 0, 0, 0 });
 173.131 +        
 173.132 +        final int ret = readShortArg(arr, 0);
 173.133 +        assert ret < 65000: "Value: " + ret;
 173.134 +        return ret;
 173.135 +    }
 173.136 +    
 173.137 +    @Compare public int readIntArgsMinus1andMinus100() {
 173.138 +        final byte[] arr = new byte[] { (byte)0, (byte)-1, (byte)-100 };
 173.139 +        
 173.140 +        assert arr[1] == -1 : "First byte: " + arr[1];
 173.141 +        assert arr[2] == -100 : "Second byte: " + arr[2];
 173.142 +        
 173.143 +        return readShortArg(arr, 0);
 173.144 +    }
 173.145 +    
 173.146 +    @Factory
 173.147 +    public static Object[] create() {
 173.148 +        return VMTest.create(ByteArithmeticTest.class);
 173.149 +    }
 173.150 +}
   174.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   174.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java	Mon Oct 07 14:20:58 2013 +0200
   174.3 @@ -0,0 +1,73 @@
   174.4 +/**
   174.5 + * Back 2 Browser Bytecode Translator
   174.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   174.7 + *
   174.8 + * This program is free software: you can redistribute it and/or modify
   174.9 + * it under the terms of the GNU General Public License as published by
  174.10 + * the Free Software Foundation, version 2 of the License.
  174.11 + *
  174.12 + * This program is distributed in the hope that it will be useful,
  174.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  174.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  174.15 + * GNU General Public License for more details.
  174.16 + *
  174.17 + * You should have received a copy of the GNU General Public License
  174.18 + * along with this program. Look for COPYING file in the top folder.
  174.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  174.20 + */
  174.21 +package org.apidesign.bck2brwsr.tck;
  174.22 +
  174.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  174.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  174.25 +import org.testng.annotations.Factory;
  174.26 +
  174.27 +/**
  174.28 + *
  174.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  174.30 + */
  174.31 +public class CloneTest {
  174.32 +    private int value;
  174.33 +    
  174.34 +    @Compare
  174.35 +    public Object notSupported() throws CloneNotSupportedException {
  174.36 +        return this.clone();
  174.37 +    }
  174.38 +
  174.39 +    @Compare public String sameClass() throws CloneNotSupportedException {
  174.40 +        return new Clnbl().clone().getClass().getName();
  174.41 +    }
  174.42 +
  174.43 +    @Compare public boolean differentInstance() throws CloneNotSupportedException {
  174.44 +        Clnbl orig = new Clnbl();
  174.45 +        return orig == orig.clone();
  174.46 +    }
  174.47 +
  174.48 +    @Compare public int sameReference() throws CloneNotSupportedException {
  174.49 +        CloneTest self = this;
  174.50 +        Clnbl orig = new Clnbl();
  174.51 +        self.value = 33;
  174.52 +        orig.ref = self;
  174.53 +        return ((Clnbl)orig.clone()).ref.value;
  174.54 +    }
  174.55 +
  174.56 +    @Compare public int sameValue() throws CloneNotSupportedException {
  174.57 +        Clnbl orig = new Clnbl();
  174.58 +        orig.value = 10;
  174.59 +        return ((Clnbl)orig.clone()).value;
  174.60 +    }
  174.61 +    
  174.62 +    @Factory
  174.63 +    public static Object[] create() {
  174.64 +        return VMTest.create(CloneTest.class);
  174.65 +    }
  174.66 +    
  174.67 +    public static final class Clnbl implements Cloneable {
  174.68 +        public CloneTest ref;
  174.69 +        private int value;
  174.70 +
  174.71 +        @Override
  174.72 +        public Object clone() throws CloneNotSupportedException {
  174.73 +            return super.clone();
  174.74 +        }
  174.75 +    }
  174.76 +}
   175.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   175.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java	Mon Oct 07 14:20:58 2013 +0200
   175.3 @@ -0,0 +1,103 @@
   175.4 +/**
   175.5 + * Back 2 Browser Bytecode Translator
   175.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   175.7 + *
   175.8 + * This program is free software: you can redistribute it and/or modify
   175.9 + * it under the terms of the GNU General Public License as published by
  175.10 + * the Free Software Foundation, version 2 of the License.
  175.11 + *
  175.12 + * This program is distributed in the hope that it will be useful,
  175.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  175.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  175.15 + * GNU General Public License for more details.
  175.16 + *
  175.17 + * You should have received a copy of the GNU General Public License
  175.18 + * along with this program. Look for COPYING file in the top folder.
  175.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  175.20 + */
  175.21 +package org.apidesign.bck2brwsr.tck;
  175.22 +
  175.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  175.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  175.25 +import org.testng.annotations.Factory;
  175.26 +
  175.27 +/**
  175.28 + *
  175.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  175.30 + */
  175.31 +public class CompareByteArrayTest {
  175.32 +    @Compare public int byteArraySum() {
  175.33 +        byte[] arr = createArray();
  175.34 +        return sumByteArr(arr);
  175.35 +    }
  175.36 +    
  175.37 +    @Compare public int countZeros() {
  175.38 +        int zeros = 0;
  175.39 +        for (Byte b : createArray()) {
  175.40 +            if (b == 0) {
  175.41 +                zeros++;
  175.42 +            }
  175.43 +        }
  175.44 +        return zeros;
  175.45 +    }
  175.46 +    
  175.47 +    private static int sumByteArr(byte[] arr) {
  175.48 +        int sum = 0;
  175.49 +        for (int i = 0; i < arr.length; i++) {
  175.50 +            sum += arr[i];
  175.51 +        }
  175.52 +        return sum;
  175.53 +    }
  175.54 +    
  175.55 +    @Compare public String noOutOfBounds() {
  175.56 +        return atIndex(1);
  175.57 +    }
  175.58 +
  175.59 +    @Compare public String outOfBounds() {
  175.60 +        return atIndex(5);
  175.61 +    }
  175.62 +
  175.63 +    @Compare public String outOfBoundsMinus() {
  175.64 +        return atIndex(-1);
  175.65 +    }
  175.66 +
  175.67 +    @Compare public String toOfBounds() {
  175.68 +        return toIndex(5);
  175.69 +    }
  175.70 +
  175.71 +    @Compare public String toOfBoundsMinus() {
  175.72 +        return toIndex(-1);
  175.73 +    }
  175.74 +    
  175.75 +    @Compare public int multiArrayLength() {
  175.76 +         int[][] arr = new int[1][0];
  175.77 +         return arr[0].length;
  175.78 +    }
  175.79 +
  175.80 +    @Compare public int multiObjectArrayLength() {
  175.81 +         Object[][] arr = new Object[1][0];
  175.82 +         return arr[0].length;
  175.83 +    }
  175.84 +
  175.85 +    private static final int[] arr = { 0, 1, 2 };
  175.86 +    public static String atIndex(int at) {
  175.87 +        return "at@" + arr[at];
  175.88 +    }
  175.89 +    public static String toIndex(int at) {
  175.90 +        arr[at] = 10;
  175.91 +        return "ok";
  175.92 +    }
  175.93 +    
  175.94 +    
  175.95 +    @Factory
  175.96 +    public static Object[] create() {
  175.97 +        return VMTest.create(CompareByteArrayTest.class);
  175.98 +    }
  175.99 +
 175.100 +    private byte[] createArray() {
 175.101 +        byte[] arr = new byte[10];
 175.102 +        arr[5] = 3;
 175.103 +        arr[7] = 8;
 175.104 +        return arr;
 175.105 +    }
 175.106 +}
   176.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   176.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Mon Oct 07 14:20:58 2013 +0200
   176.3 @@ -0,0 +1,60 @@
   176.4 +/**
   176.5 + * Back 2 Browser Bytecode Translator
   176.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   176.7 + *
   176.8 + * This program is free software: you can redistribute it and/or modify
   176.9 + * it under the terms of the GNU General Public License as published by
  176.10 + * the Free Software Foundation, version 2 of the License.
  176.11 + *
  176.12 + * This program is distributed in the hope that it will be useful,
  176.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  176.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  176.15 + * GNU General Public License for more details.
  176.16 + *
  176.17 + * You should have received a copy of the GNU General Public License
  176.18 + * along with this program. Look for COPYING file in the top folder.
  176.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  176.20 + */
  176.21 +package org.apidesign.bck2brwsr.tck;
  176.22 +
  176.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  176.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  176.25 +import org.testng.annotations.Factory;
  176.26 +
  176.27 +/**
  176.28 + *
  176.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  176.30 + */
  176.31 +public class CompareHashTest {
  176.32 +    @Compare public int hashOfString() {
  176.33 +        return "Ahoj".hashCode();
  176.34 +    }
  176.35 +    
  176.36 +    @Compare public boolean hashOfIntegerDifferentToOwnHash() {
  176.37 +        Integer i = 120;
  176.38 +        return System.identityHashCode(i) != i.hashCode();
  176.39 +    }
  176.40 +
  176.41 +    @Compare public int hashOfObjectSameAsOwnHash() {
  176.42 +        Object o = new Object();
  176.43 +        return System.identityHashCode(o) - o.hashCode();
  176.44 +    }
  176.45 +    
  176.46 +    @Compare public int hashRemainsYieldsZero() {
  176.47 +        Object o = new Object();
  176.48 +        return o.hashCode() - o.hashCode();
  176.49 +    }
  176.50 +    
  176.51 +    @Compare public int initializeInStatic() {
  176.52 +        return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
  176.53 +    }
  176.54 +    
  176.55 +    @Compare public int hashOfInt() {
  176.56 +        return Integer.valueOf(Integer.MAX_VALUE).hashCode();
  176.57 +    }
  176.58 +    
  176.59 +    @Factory
  176.60 +    public static Object[] create() {
  176.61 +        return VMTest.create(CompareHashTest.class);
  176.62 +    }
  176.63 +}
   177.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   177.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java	Mon Oct 07 14:20:58 2013 +0200
   177.3 @@ -0,0 +1,63 @@
   177.4 +/**
   177.5 + * Back 2 Browser Bytecode Translator
   177.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   177.7 + *
   177.8 + * This program is free software: you can redistribute it and/or modify
   177.9 + * it under the terms of the GNU General Public License as published by
  177.10 + * the Free Software Foundation, version 2 of the License.
  177.11 + *
  177.12 + * This program is distributed in the hope that it will be useful,
  177.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  177.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  177.15 + * GNU General Public License for more details.
  177.16 + *
  177.17 + * You should have received a copy of the GNU General Public License
  177.18 + * along with this program. Look for COPYING file in the top folder.
  177.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  177.20 + */
  177.21 +package org.apidesign.bck2brwsr.tck;
  177.22 +
  177.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  177.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  177.25 +import org.testng.annotations.Factory;
  177.26 +
  177.27 +/**
  177.28 + *
  177.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  177.30 + */
  177.31 +public class CompareIntArrayTest {
  177.32 +    @Compare public int integerArraySum() {
  177.33 +        int[] arr = createArray();
  177.34 +        return sumIntArr(arr);
  177.35 +    }
  177.36 +    
  177.37 +    @Compare public int countZeros() {
  177.38 +        int zeros = 0;
  177.39 +        for (Integer i : createArray()) {
  177.40 +            if (i == 0) {
  177.41 +                zeros++;
  177.42 +            }
  177.43 +        }
  177.44 +        return zeros;
  177.45 +    }
  177.46 +    
  177.47 +    private static int sumIntArr(int[] arr) {
  177.48 +        int sum = 0;
  177.49 +        for (int i = 0; i < arr.length; i++) {
  177.50 +            sum += arr[i];
  177.51 +        }
  177.52 +        return sum;
  177.53 +    }
  177.54 +    
  177.55 +    @Factory
  177.56 +    public static Object[] create() {
  177.57 +        return VMTest.create(CompareIntArrayTest.class);
  177.58 +    }
  177.59 +
  177.60 +    private int[] createArray() {
  177.61 +        int[] arr = new int[10];
  177.62 +        arr[5] = 3;
  177.63 +        arr[7] = 8;
  177.64 +        return arr;
  177.65 +    }
  177.66 +}
   178.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   178.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Mon Oct 07 14:20:58 2013 +0200
   178.3 @@ -0,0 +1,174 @@
   178.4 +/**
   178.5 + * Back 2 Browser Bytecode Translator
   178.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   178.7 + *
   178.8 + * This program is free software: you can redistribute it and/or modify
   178.9 + * it under the terms of the GNU General Public License as published by
  178.10 + * the Free Software Foundation, version 2 of the License.
  178.11 + *
  178.12 + * This program is distributed in the hope that it will be useful,
  178.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  178.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  178.15 + * GNU General Public License for more details.
  178.16 + *
  178.17 + * You should have received a copy of the GNU General Public License
  178.18 + * along with this program. Look for COPYING file in the top folder.
  178.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  178.20 + */
  178.21 +package org.apidesign.bck2brwsr.tck;
  178.22 +
  178.23 +import java.io.UnsupportedEncodingException;
  178.24 +import java.net.MalformedURLException;
  178.25 +import java.net.URL;
  178.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
  178.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  178.28 +import org.testng.annotations.Factory;
  178.29 +
  178.30 +/**
  178.31 + *
  178.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  178.33 + */
  178.34 +public class CompareStringsTest {
  178.35 +    @Compare public String firstChar() {
  178.36 +        return "" + ("Hello".toCharArray()[0]);
  178.37 +    }
  178.38 +    
  178.39 +    @Compare public String classCast() {
  178.40 +        Object o = firstChar();
  178.41 +        return String.class.cast(o);
  178.42 +    }
  178.43 +
  178.44 +    @Compare public String classCastThrown() {
  178.45 +        Object o = null;
  178.46 +        return String.class.cast(o);
  178.47 +    }
  178.48 +    
  178.49 +    @Compare public boolean equalToNull() {
  178.50 +        return "Ahoj".equals(null);
  178.51 +    }
  178.52 +    
  178.53 +    @Compare public int highByteLenght() {
  178.54 +        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
  178.55 +        return new String(arr, 0).length();
  178.56 +    }
  178.57 +    
  178.58 +    @Compare public String highByte() {
  178.59 +        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
  178.60 +        StringBuilder sb = new StringBuilder();
  178.61 +        sb.append("pref:");
  178.62 +        sb.append(new String(arr, 0));
  178.63 +        return sb.toString();
  178.64 +    }
  178.65 +    
  178.66 +    @Compare public static Object compareURLs() throws MalformedURLException {
  178.67 +        return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
  178.68 +    }
  178.69 +    
  178.70 +    @Compare public String deleteLastTwoCharacters() {
  178.71 +        StringBuilder sb = new StringBuilder();
  178.72 +        sb.append("453.0");
  178.73 +        if (sb.toString().endsWith(".0")) {
  178.74 +            final int l = sb.length();
  178.75 +            sb.delete(l - 2, l);
  178.76 +        }
  178.77 +        return sb.toString().toString();
  178.78 +    }
  178.79 +    
  178.80 +    @Compare public String nameOfStringClass() throws Exception {
  178.81 +        return Class.forName("java.lang.String").getName();
  178.82 +    }
  178.83 +    @Compare public String nameOfArrayClass() throws Exception {
  178.84 +        return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
  178.85 +    }
  178.86 +    
  178.87 +    @Compare public String lowerHello() {
  178.88 +        return "HeLlO".toLowerCase();
  178.89 +    }
  178.90 +    
  178.91 +    @Compare public String lowerA() {
  178.92 +        return String.valueOf(Character.toLowerCase('A')).toString();
  178.93 +    }
  178.94 +    @Compare public String upperHello() {
  178.95 +        return "hello".toUpperCase();
  178.96 +    }
  178.97 +    
  178.98 +    @Compare public String upperA() {
  178.99 +        return String.valueOf(Character.toUpperCase('a')).toString();
 178.100 +    }
 178.101 +    
 178.102 +    @Compare public boolean matchRegExp() throws Exception {
 178.103 +        return "58038503".matches("\\d*");
 178.104 +    }
 178.105 +
 178.106 +    @Compare public boolean doesNotMatchRegExp() throws Exception {
 178.107 +        return "58038503GH".matches("\\d*");
 178.108 +    }
 178.109 +
 178.110 +    @Compare public boolean doesNotMatchRegExpFully() throws Exception {
 178.111 +        return "Hello".matches("Hell");
 178.112 +    }
 178.113 +    
 178.114 +    @Compare public String emptyCharArray() {
 178.115 +        char[] arr = new char[10];
 178.116 +        return new String(arr);
 178.117 +    }
 178.118 +    
 178.119 +    @Compare public String variousCharacterTests() throws Exception {
 178.120 +        StringBuilder sb = new StringBuilder();
 178.121 +        
 178.122 +        sb.append(Character.isUpperCase('a'));
 178.123 +        sb.append(Character.isUpperCase('A'));
 178.124 +        sb.append(Character.isLowerCase('a'));
 178.125 +        sb.append(Character.isLowerCase('A'));
 178.126 +        
 178.127 +        sb.append(Character.isLetter('A'));
 178.128 +        sb.append(Character.isLetterOrDigit('9'));
 178.129 +        sb.append(Character.isLetterOrDigit('A'));
 178.130 +        sb.append(Character.isLetter('0'));
 178.131 +        
 178.132 +        return sb.toString().toString();
 178.133 +    }
 178.134 +        
 178.135 +    @Compare
 178.136 +    public String nullFieldInitialized() {
 178.137 +        NullField nf = new NullField();
 178.138 +        return ("" + nf.name).toString();
 178.139 +    }
 178.140 +    @Compare
 178.141 +    public String toUTFString() throws UnsupportedEncodingException {
 178.142 +        byte[] arr = {
 178.143 +            (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
 178.144 +            (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
 178.145 +            (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
 178.146 +            (byte) -120
 178.147 +        };
 178.148 +        return new String(arr, "utf-8");
 178.149 +    }
 178.150 +
 178.151 +    @Compare
 178.152 +    public int stringToBytesLenght() throws UnsupportedEncodingException {
 178.153 +        return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
 178.154 +    }
 178.155 +    
 178.156 +    @Compare public String replaceSeq() {
 178.157 +        return "Hello World.".replace(".", "!");
 178.158 +    }
 178.159 +    @Compare public String replaceSeqAll() {
 178.160 +        return "Hello World! Hello World.".replace("World", "Jarda");
 178.161 +    }
 178.162 +    @Compare public String replaceSeqAA() {
 178.163 +        String res = "aaa".replace("aa", "b");
 178.164 +        assert res.equals("ba") : "Expecting ba: " + res;
 178.165 +        return res;
 178.166 +    }
 178.167 +
 178.168 +    @Factory
 178.169 +    public static Object[] create() {
 178.170 +        return VMTest.create(CompareStringsTest.class);
 178.171 +    }
 178.172 +
 178.173 +    private static final class NullField {
 178.174 +
 178.175 +        String name;
 178.176 +    }
 178.177 +}
   179.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   179.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/DoubleTest.java	Mon Oct 07 14:20:58 2013 +0200
   179.3 @@ -0,0 +1,69 @@
   179.4 +/**
   179.5 + * Back 2 Browser Bytecode Translator
   179.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   179.7 + *
   179.8 + * This program is free software: you can redistribute it and/or modify
   179.9 + * it under the terms of the GNU General Public License as published by
  179.10 + * the Free Software Foundation, version 2 of the License.
  179.11 + *
  179.12 + * This program is distributed in the hope that it will be useful,
  179.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  179.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  179.15 + * GNU General Public License for more details.
  179.16 + *
  179.17 + * You should have received a copy of the GNU General Public License
  179.18 + * along with this program. Look for COPYING file in the top folder.
  179.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  179.20 + */
  179.21 +package org.apidesign.bck2brwsr.tck;
  179.22 +
  179.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  179.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  179.25 +import org.testng.annotations.Factory;
  179.26 +
  179.27 +/**
  179.28 + *
  179.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  179.30 + */
  179.31 +public class DoubleTest {
  179.32 +    @Compare public boolean parsedDoubleIsDouble() {
  179.33 +        return Double.valueOf("1.1") instanceof Double;
  179.34 +    }
  179.35 +    
  179.36 +    @Compare public String integerToString() {
  179.37 +        return toStr(1);
  179.38 +    }
  179.39 +
  179.40 +    @Compare public String integerAndHalfToString() {
  179.41 +        return toStr(1.5);
  179.42 +    }
  179.43 +
  179.44 +    @Compare public double longToAndBack() {
  179.45 +        return Double.parseDouble(toStr(Long.MAX_VALUE / 10));
  179.46 +    }
  179.47 +
  179.48 +    @Compare public String negativeIntToString() {
  179.49 +        return toStr(-10);
  179.50 +    }
  179.51 +
  179.52 +    @Compare public String negativeIntAndHalfToString() {
  179.53 +        return toStr(-10.5);
  179.54 +    }
  179.55 +
  179.56 +    @Compare public double negativeLongAndBack() {
  179.57 +        return Double.parseDouble(toStr(Long.MIN_VALUE / 10));
  179.58 +    }
  179.59 +    
  179.60 +    @Compare public double canParseExp() {
  179.61 +        return Double.parseDouble(toStr(1.7976931348623157e+308));
  179.62 +    }
  179.63 +    
  179.64 +    private static String toStr(double d) {
  179.65 +        return Double.toString(d);
  179.66 +    }
  179.67 +    
  179.68 +    @Factory 
  179.69 +    public static Object[] create() {
  179.70 +        return VMTest.create(DoubleTest.class);
  179.71 +    }
  179.72 +}
   180.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   180.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/EnumsTest.java	Mon Oct 07 14:20:58 2013 +0200
   180.3 @@ -0,0 +1,61 @@
   180.4 +package org.apidesign.bck2brwsr.tck;
   180.5 +
   180.6 +import java.util.EnumMap;
   180.7 +import java.util.EnumSet;
   180.8 +import org.apidesign.bck2brwsr.vmtest.Compare;
   180.9 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  180.10 +import org.testng.annotations.Factory;
  180.11 +
  180.12 +/**
  180.13 + *
  180.14 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  180.15 + */
  180.16 +public class EnumsTest {
  180.17 +    enum Color {
  180.18 +        B, W;
  180.19 +    }
  180.20 +
  180.21 +    /*
  180.22 +    @Compare public String enumSet() {
  180.23 +        try { throw new Exception(); } catch (Exception ex) {}
  180.24 +        EnumSet<Color> c = EnumSet.allOf(Color.class);
  180.25 +        return c.toString();
  180.26 +    }
  180.27 +
  180.28 +    @Compare public String enumSetOneByOne() {
  180.29 +        EnumSet<Color> c = EnumSet.of(Color.B, Color.W);
  180.30 +        return c.toString();
  180.31 +    }
  180.32 +    */
  180.33 +
  180.34 +    @Compare public boolean enumFirstContains() {
  180.35 +        EnumSet<Color> c = EnumSet.of(Color.B);
  180.36 +        return c.contains(Color.B);
  180.37 +    }
  180.38 +
  180.39 +    @Compare public boolean enumFirstDoesNotContains() {
  180.40 +        EnumSet<Color> c = EnumSet.of(Color.B);
  180.41 +        return c.contains(Color.W);
  180.42 +    }
  180.43 +
  180.44 +    @Compare public boolean enumSndContains() {
  180.45 +        EnumSet<Color> c = EnumSet.of(Color.W);
  180.46 +        return c.contains(Color.W);
  180.47 +    }
  180.48 +
  180.49 +    @Compare public boolean enumSecondDoesNotContains() {
  180.50 +        EnumSet<Color> c = EnumSet.of(Color.W);
  180.51 +        return c.contains(Color.B);
  180.52 +    }
  180.53 +
  180.54 +    @Compare public String enumMap() {
  180.55 +        EnumMap<Color,String> c = new EnumMap(Color.class);
  180.56 +        c.put(Color.B, "Black");
  180.57 +        c.put(Color.W, "White");
  180.58 +        return c.toString();
  180.59 +    }
  180.60 +    
  180.61 +    @Factory public static Object[] create() {
  180.62 +        return VMTest.create(EnumsTest.class);
  180.63 +    }
  180.64 +}
   181.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   181.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java	Mon Oct 07 14:20:58 2013 +0200
   181.3 @@ -0,0 +1,106 @@
   181.4 +/**
   181.5 + * Back 2 Browser Bytecode Translator
   181.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   181.7 + *
   181.8 + * This program is free software: you can redistribute it and/or modify
   181.9 + * it under the terms of the GNU General Public License as published by
  181.10 + * the Free Software Foundation, version 2 of the License.
  181.11 + *
  181.12 + * This program is distributed in the hope that it will be useful,
  181.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  181.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  181.15 + * GNU General Public License for more details.
  181.16 + *
  181.17 + * You should have received a copy of the GNU General Public License
  181.18 + * along with this program. Look for COPYING file in the top folder.
  181.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  181.20 + */
  181.21 +package org.apidesign.bck2brwsr.tck;
  181.22 +
  181.23 +import java.io.InputStream;
  181.24 +import java.net.URL;
  181.25 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  181.26 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  181.27 +import org.apidesign.bck2brwsr.vmtest.Http;
  181.28 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  181.29 +import org.testng.annotations.Factory;
  181.30 +
  181.31 +/**
  181.32 + *
  181.33 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  181.34 + */
  181.35 +public class HttpResourceTest {
  181.36 +    
  181.37 +    @Http({
  181.38 +        @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
  181.39 +    })
  181.40 +    @BrwsrTest
  181.41 +    
  181.42 +    
  181.43 +    public String testReadContentViaXHR() throws Exception {
  181.44 +        String msg = read("/xhr");
  181.45 +        assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
  181.46 +        return msg;
  181.47 +    }
  181.48 +
  181.49 +    @Http({
  181.50 +        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
  181.51 +    })
  181.52 +    @BrwsrTest
  181.53 +    public String testReadContentViaURL() throws Exception {
  181.54 +        URL url = new URL("http:/url");
  181.55 +        String msg = (String) url.getContent();
  181.56 +        assert "Hello via URL!".equals(msg) : "The message was " + msg;
  181.57 +        return msg;
  181.58 +    }
  181.59 +    @Http({
  181.60 +        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
  181.61 +    })
  181.62 +    @BrwsrTest
  181.63 +    public String testReadContentViaURLWithStringParam() throws Exception {
  181.64 +        URL url = new URL("http:/url");
  181.65 +        String msg = (String) url.getContent(new Class[] { String.class });
  181.66 +        assert "Hello via URL!".equals(msg) : "The message was " + msg;
  181.67 +        return msg;
  181.68 +    }
  181.69 +
  181.70 +    @Http({
  181.71 +        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
  181.72 +    })
  181.73 +    @BrwsrTest
  181.74 +    public void testReadByte() throws Exception {
  181.75 +        URL url = new URL("http:/bytes");
  181.76 +        final Object res = url.getContent(new Class[] { byte[].class });
  181.77 +        assert res instanceof byte[] : "Expecting byte[]: " + res;
  181.78 +        byte[] arr = (byte[]) res;
  181.79 +        assert arr.length == 1 : "One byte " + arr.length;
  181.80 +        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
  181.81 +    }
  181.82 +
  181.83 +    @Http({
  181.84 +        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
  181.85 +    })
  181.86 +    @BrwsrTest
  181.87 +    public void testReadByteViaInputStream() throws Exception {
  181.88 +        URL url = new URL("http:/bytes");
  181.89 +        InputStream is = url.openStream();
  181.90 +        byte[] arr = new byte[10];
  181.91 +        int len = is.read(arr);
  181.92 +        assert len == 1 : "One byte " + len;
  181.93 +        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
  181.94 +    }
  181.95 +    
  181.96 +    @JavaScriptBody(args = { "url" }, body = 
  181.97 +          "var req = new XMLHttpRequest();\n"
  181.98 +        + "req.open('GET', url, false);\n"
  181.99 +        + "req.send();\n"
 181.100 +        + "return req.responseText;"
 181.101 +    )
 181.102 +    private static native String read(String url);
 181.103 +    
 181.104 +    
 181.105 +    @Factory
 181.106 +    public static Object[] create() {
 181.107 +        return VMTest.create(HttpResourceTest.class);
 181.108 +    }
 181.109 +}
   182.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   182.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java	Mon Oct 07 14:20:58 2013 +0200
   182.3 @@ -0,0 +1,34 @@
   182.4 +/**
   182.5 + * Back 2 Browser Bytecode Translator
   182.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   182.7 + *
   182.8 + * This program is free software: you can redistribute it and/or modify
   182.9 + * it under the terms of the GNU General Public License as published by
  182.10 + * the Free Software Foundation, version 2 of the License.
  182.11 + *
  182.12 + * This program is distributed in the hope that it will be useful,
  182.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  182.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  182.15 + * GNU General Public License for more details.
  182.16 + *
  182.17 + * You should have received a copy of the GNU General Public License
  182.18 + * along with this program. Look for COPYING file in the top folder.
  182.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  182.20 + */
  182.21 +package org.apidesign.bck2brwsr.tck;
  182.22 +
  182.23 +/**
  182.24 + *
  182.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  182.26 + */
  182.27 +public class InheritanceA {
  182.28 +    private String name;
  182.29 +    
  182.30 +    public void setA(String n) {
  182.31 +        this.name = n;
  182.32 +    }
  182.33 +    
  182.34 +    public String getA() {
  182.35 +        return name;
  182.36 +    }
  182.37 +}
   183.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   183.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java	Mon Oct 07 14:20:58 2013 +0200
   183.3 @@ -0,0 +1,34 @@
   183.4 +/**
   183.5 + * Back 2 Browser Bytecode Translator
   183.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   183.7 + *
   183.8 + * This program is free software: you can redistribute it and/or modify
   183.9 + * it under the terms of the GNU General Public License as published by
  183.10 + * the Free Software Foundation, version 2 of the License.
  183.11 + *
  183.12 + * This program is distributed in the hope that it will be useful,
  183.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  183.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  183.15 + * GNU General Public License for more details.
  183.16 + *
  183.17 + * You should have received a copy of the GNU General Public License
  183.18 + * along with this program. Look for COPYING file in the top folder.
  183.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  183.20 + */
  183.21 +package org.apidesign.bck2brwsr.tck;
  183.22 +
  183.23 +/**
  183.24 + *
  183.25 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  183.26 + */
  183.27 +public class InheritanceB extends InheritanceA {
  183.28 +    private String name;
  183.29 +    
  183.30 +    public void setB(String n) {
  183.31 +        this.name = n;
  183.32 +    }
  183.33 +    
  183.34 +    public String getB() {
  183.35 +        return name;
  183.36 +    }
  183.37 +}
   184.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   184.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java	Mon Oct 07 14:20:58 2013 +0200
   184.3 @@ -0,0 +1,41 @@
   184.4 +/**
   184.5 + * Back 2 Browser Bytecode Translator
   184.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   184.7 + *
   184.8 + * This program is free software: you can redistribute it and/or modify
   184.9 + * it under the terms of the GNU General Public License as published by
  184.10 + * the Free Software Foundation, version 2 of the License.
  184.11 + *
  184.12 + * This program is distributed in the hope that it will be useful,
  184.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  184.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  184.15 + * GNU General Public License for more details.
  184.16 + *
  184.17 + * You should have received a copy of the GNU General Public License
  184.18 + * along with this program. Look for COPYING file in the top folder.
  184.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  184.20 + */
  184.21 +package org.apidesign.bck2brwsr.tck;
  184.22 +
  184.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  184.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  184.25 +import org.testng.annotations.Factory;
  184.26 +
  184.27 +/**
  184.28 + *
  184.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  184.30 + */
  184.31 +public class InheritanceTest {
  184.32 +
  184.33 +    @Compare public String checkFieldsIndependent() throws ClassNotFoundException {
  184.34 +        InheritanceB ib = new InheritanceB();
  184.35 +        ib.setA("A");
  184.36 +        ib.setB("B");
  184.37 +        return "A: " + ib.getA() + " B: " + ib.getB();
  184.38 +    }
  184.39 +    
  184.40 +    @Factory
  184.41 +    public static Object[] create() {
  184.42 +        return VMTest.create(InheritanceTest.class);
  184.43 +    }
  184.44 +}
   185.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   185.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java	Mon Oct 07 14:20:58 2013 +0200
   185.3 @@ -0,0 +1,166 @@
   185.4 +/**
   185.5 + * Back 2 Browser Bytecode Translator
   185.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   185.7 + *
   185.8 + * This program is free software: you can redistribute it and/or modify
   185.9 + * it under the terms of the GNU General Public License as published by
  185.10 + * the Free Software Foundation, version 2 of the License.
  185.11 + *
  185.12 + * This program is distributed in the hope that it will be useful,
  185.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  185.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  185.15 + * GNU General Public License for more details.
  185.16 + *
  185.17 + * You should have received a copy of the GNU General Public License
  185.18 + * along with this program. Look for COPYING file in the top folder.
  185.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  185.20 + */
  185.21 +package org.apidesign.bck2brwsr.tck;
  185.22 +
  185.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  185.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  185.25 +import org.testng.annotations.Factory;
  185.26 +
  185.27 +/**
  185.28 + *
  185.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  185.30 + */
  185.31 +public class IntegerArithmeticTest {
  185.32 +    
  185.33 +    private static int add(int x, int y) {
  185.34 +        return x + y;
  185.35 +    }
  185.36 +    
  185.37 +    private static int sub(int x, int y) {
  185.38 +        return x - y;
  185.39 +    }
  185.40 +    
  185.41 +    private static int mul(int x, int y) {
  185.42 +        return x * y;
  185.43 +    }
  185.44 +    
  185.45 +    private static int div(int x, int y) {
  185.46 +        return x / y;
  185.47 +    }
  185.48 +    
  185.49 +    private static int mod(int x, int y) {
  185.50 +        return x % y;
  185.51 +    }
  185.52 +    
  185.53 +    private static int neg(int x) {
  185.54 +        return (-x);
  185.55 +    }
  185.56 +
  185.57 +    private static float fadd(float x, float y) {
  185.58 +        return x + y;
  185.59 +    }
  185.60 +
  185.61 +    private static double dadd(double x, double y) {
  185.62 +        return x + y;
  185.63 +    }
  185.64 +    
  185.65 +    @Compare public int addOverflow() {
  185.66 +        return add(Integer.MAX_VALUE, 1);
  185.67 +    }
  185.68 +    
  185.69 +    @Compare public int subUnderflow() {
  185.70 +        return sub(Integer.MIN_VALUE, 1);
  185.71 +    }
  185.72 +    
  185.73 +    @Compare public int addMaxIntAndMaxInt() {
  185.74 +        return add(Integer.MAX_VALUE, Integer.MAX_VALUE);
  185.75 +    }
  185.76 +    
  185.77 +    @Compare public int subMinIntAndMinInt() {
  185.78 +        return sub(Integer.MIN_VALUE, Integer.MIN_VALUE);
  185.79 +    }
  185.80 +    
  185.81 +    @Compare public int multiplyMaxInt() {
  185.82 +        return mul(Integer.MAX_VALUE, 2);
  185.83 +    }
  185.84 +    
  185.85 +    @Compare public int multiplyMaxIntAndMaxInt() {
  185.86 +        return mul(Integer.MAX_VALUE, Integer.MAX_VALUE);
  185.87 +    }
  185.88 +    
  185.89 +    @Compare public int multiplyMinInt() {
  185.90 +        return mul(Integer.MIN_VALUE, 2);
  185.91 +    }
  185.92 +    
  185.93 +    @Compare public int multiplyMinIntAndMinInt() {
  185.94 +        return mul(Integer.MIN_VALUE, Integer.MIN_VALUE);
  185.95 +    }
  185.96 +    
  185.97 +    @Compare public int multiplyPrecision() {
  185.98 +        return mul(119106029, 1103515245);
  185.99 +    }
 185.100 +    
 185.101 +    @Compare public int division() {
 185.102 +        return div(1, 2);
 185.103 +    }
 185.104 +
 185.105 +    @Compare public int divisionReminder() {
 185.106 +        return mod(1, 2);
 185.107 +    }
 185.108 +
 185.109 +    @Compare public int negativeDivision() {
 185.110 +        return div(-7, 3);
 185.111 +    }
 185.112 +
 185.113 +    @Compare public int negativeDivisionReminder() {
 185.114 +        return mod(-7, 3);
 185.115 +    }
 185.116 +
 185.117 +    @Compare public int conversionFromFloat() {
 185.118 +        return (int) fadd(-2, -0.6f);
 185.119 +    }
 185.120 +
 185.121 +    @Compare public int conversionFromDouble() {
 185.122 +        return (int) dadd(-2, -0.6);
 185.123 +    }
 185.124 +
 185.125 +    @Compare public boolean divByZeroThrowsArithmeticException() {
 185.126 +        try {
 185.127 +            div(1, 0);
 185.128 +            return false;
 185.129 +        } catch (final ArithmeticException e) {
 185.130 +            return true;
 185.131 +        }
 185.132 +    }
 185.133 +
 185.134 +    @Compare public boolean modByZeroThrowsArithmeticException() {
 185.135 +        try {
 185.136 +            mod(1, 0);
 185.137 +            return false;
 185.138 +        } catch (final ArithmeticException e) {
 185.139 +            return true;
 185.140 +        }
 185.141 +    }
 185.142 +
 185.143 +    @Compare public int negate() {
 185.144 +        return neg(123456);
 185.145 +    }
 185.146 +    
 185.147 +    @Compare public int negateMaxInt() {
 185.148 +        return neg(Integer.MAX_VALUE);
 185.149 +    }
 185.150 +    
 185.151 +    @Compare public int negateMinInt() {
 185.152 +        return neg(Integer.MIN_VALUE);
 185.153 +    }
 185.154 +    
 185.155 +    @Compare public int sumTwoDimensions() {
 185.156 +        int[][] matrix = createMatrix(4, 3);
 185.157 +        matrix[0][0] += 10;
 185.158 +        return matrix[0][0];
 185.159 +    }
 185.160 +    
 185.161 +    static int[][] createMatrix(int x, int y) {
 185.162 +        return new int[x][y];
 185.163 +    }
 185.164 +    
 185.165 +    @Factory
 185.166 +    public static Object[] create() {
 185.167 +        return VMTest.create(IntegerArithmeticTest.class);
 185.168 +    }
 185.169 +}
   186.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   186.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LoggerTest.java	Mon Oct 07 14:20:58 2013 +0200
   186.3 @@ -0,0 +1,43 @@
   186.4 +/**
   186.5 + * Back 2 Browser Bytecode Translator
   186.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   186.7 + *
   186.8 + * This program is free software: you can redistribute it and/or modify
   186.9 + * it under the terms of the GNU General Public License as published by
  186.10 + * the Free Software Foundation, version 2 of the License.
  186.11 + *
  186.12 + * This program is distributed in the hope that it will be useful,
  186.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  186.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  186.15 + * GNU General Public License for more details.
  186.16 + *
  186.17 + * You should have received a copy of the GNU General Public License
  186.18 + * along with this program. Look for COPYING file in the top folder.
  186.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  186.20 + */
  186.21 +package org.apidesign.bck2brwsr.tck;
  186.22 +
  186.23 +import java.util.logging.Logger;
  186.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  186.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  186.26 +import org.testng.annotations.Factory;
  186.27 +
  186.28 +/**
  186.29 + *
  186.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  186.31 + */
  186.32 +public class LoggerTest {
  186.33 +    @Compare public String parentLogger() {
  186.34 +        Logger lx = Logger.getLogger("x");
  186.35 +        assert lx != null;
  186.36 +        assert lx.getName().equals("x") : "Right name: " + lx.getName();
  186.37 +        Logger lxyz = Logger.getLogger("x.y.z");
  186.38 +        assert lxyz != null;
  186.39 +        assert lxyz.getName().equals("x.y.z") : "xyz name: " + lxyz.getName();
  186.40 +        return lxyz.getParent().getName();
  186.41 +    }
  186.42 +    
  186.43 +    @Factory public static Object[] create() {
  186.44 +        return VMTest.create(LoggerTest.class);
  186.45 +    }
  186.46 +}
   187.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   187.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Mon Oct 07 14:20:58 2013 +0200
   187.3 @@ -0,0 +1,376 @@
   187.4 +/**
   187.5 + * Back 2 Browser Bytecode Translator
   187.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   187.7 + *
   187.8 + * This program is free software: you can redistribute it and/or modify
   187.9 + * it under the terms of the GNU General Public License as published by
  187.10 + * the Free Software Foundation, version 2 of the License.
  187.11 + *
  187.12 + * This program is distributed in the hope that it will be useful,
  187.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  187.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  187.15 + * GNU General Public License for more details.
  187.16 + *
  187.17 + * You should have received a copy of the GNU General Public License
  187.18 + * along with this program. Look for COPYING file in the top folder.
  187.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  187.20 + */
  187.21 +package org.apidesign.bck2brwsr.tck;
  187.22 +
  187.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  187.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  187.25 +import org.testng.annotations.Factory;
  187.26 +
  187.27 +/**
  187.28 + *
  187.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  187.30 + */
  187.31 +public class LongArithmeticTest {
  187.32 +
  187.33 +    private static long add(long x, long y) {
  187.34 +        return (x + y);
  187.35 +    }
  187.36 +
  187.37 +    private static long sub(long x, long y) {
  187.38 +        return (x - y);
  187.39 +    }
  187.40 +
  187.41 +    private static long mul(long x, long y) {
  187.42 +        return (x * y);
  187.43 +    }
  187.44 +
  187.45 +    private static long div(long x, long y) {
  187.46 +        return (x / y);
  187.47 +    }
  187.48 +
  187.49 +    private static long mod(long x, long y) {
  187.50 +        return (x % y);
  187.51 +    }
  187.52 +
  187.53 +    private static long neg(long x) {
  187.54 +        return (-x);
  187.55 +    }
  187.56 +
  187.57 +    private static long shl(long x, int b) {
  187.58 +        return (x << b);
  187.59 +    }
  187.60 +
  187.61 +    private static long shr(long x, int b) {
  187.62 +        return (x >> b);
  187.63 +    }
  187.64 +
  187.65 +    private static long ushr(long x, int b) {
  187.66 +        return (x >>> b);
  187.67 +    }
  187.68 +
  187.69 +    private static long and(long x, long y) {
  187.70 +        return (x & y);
  187.71 +    }
  187.72 +
  187.73 +    private static long or(long x, long y) {
  187.74 +        return (x | y);
  187.75 +    }
  187.76 +
  187.77 +    private static long xor(long x, long y) {
  187.78 +        return (x ^ y);
  187.79 +    }
  187.80 +
  187.81 +    private static float fadd(float x, float y) {
  187.82 +        return x + y;
  187.83 +    }
  187.84 +
  187.85 +    private static double dadd(double x, double y) {
  187.86 +        return x + y;
  187.87 +    }
  187.88 +
  187.89 +    public static int compare(long x, long y, int zero) {
  187.90 +        final int xyResult = compareL(x, y, zero);
  187.91 +        final int yxResult = compareL(y, x, zero);
  187.92 +
  187.93 +        return ((xyResult + yxResult) == 0) ? xyResult : -2;
  187.94 +    }
  187.95 +
  187.96 +    private static int compareL(long x, long y, int zero) {
  187.97 +        int result = -2;
  187.98 +        int trueCount = 0;
  187.99 +
 187.100 +        x += zero;
 187.101 +        if (x == y) {
 187.102 +            result = 0;
 187.103 +            ++trueCount;
 187.104 +        }
 187.105 +
 187.106 +        x += zero;
 187.107 +        if (x < y) {
 187.108 +            result = -1;
 187.109 +            ++trueCount;
 187.110 +        }
 187.111 +
 187.112 +        x += zero;
 187.113 +        if (x > y) {
 187.114 +            result = 1;
 187.115 +            ++trueCount;
 187.116 +        }
 187.117 +
 187.118 +        return (trueCount == 1) ? result : -2;
 187.119 +    }
 187.120 +
 187.121 +    @Compare public long conversion() {
 187.122 +        return Long.MAX_VALUE;
 187.123 +    }
 187.124 +
 187.125 +    @Compare public long negate1() {
 187.126 +        return neg(0x00fa37d7763e0ca1l);
 187.127 +    }
 187.128 +
 187.129 +    @Compare public long negate2() {
 187.130 +        return neg(0x80fa37d7763e0ca1l);
 187.131 +    }
 187.132 +
 187.133 +    @Compare public long negate3() {
 187.134 +        return neg(0xfffffffffffffeddl);
 187.135 +    }
 187.136 +
 187.137 +    @Compare public long addOverflow() {
 187.138 +        return add(Long.MAX_VALUE, 1l);
 187.139 +    }
 187.140 +
 187.141 +    @Compare public long subUnderflow() {
 187.142 +        return sub(Long.MIN_VALUE, 1l);
 187.143 +    }
 187.144 +
 187.145 +    @Compare public long addMaxLongAndMaxLong() {
 187.146 +        return add(Long.MAX_VALUE, Long.MAX_VALUE);
 187.147 +    }
 187.148 +
 187.149 +    @Compare public long subMinLongAndMinLong() {
 187.150 +        return sub(Long.MIN_VALUE, Long.MIN_VALUE);
 187.151 +    }
 187.152 +
 187.153 +    @Compare public long subMinLongAndMaxLong() {
 187.154 +        return sub(Long.MIN_VALUE, Long.MAX_VALUE);
 187.155 +    }
 187.156 +
 187.157 +    @Compare public long multiplyMaxLong() {
 187.158 +        return mul(Long.MAX_VALUE, 2l);
 187.159 +    }
 187.160 +
 187.161 +    @Compare public long multiplyMaxLongAndMaxLong() {
 187.162 +        return mul(Long.MAX_VALUE, Long.MAX_VALUE);
 187.163 +    }
 187.164 +
 187.165 +    @Compare public long multiplyMinLong() {
 187.166 +        return mul(Long.MIN_VALUE, 2l);
 187.167 +    }
 187.168 +
 187.169 +    @Compare public long multiplyMinLongAndMinLong() {
 187.170 +        return mul(Long.MIN_VALUE, Long.MIN_VALUE);
 187.171 +    }
 187.172 +
 187.173 +    @Compare public long multiplyPrecision() {
 187.174 +        return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 187.175 +    }
 187.176 +
 187.177 +    @Compare public long divideSmallPositiveNumbers() {
 187.178 +        return div(0xabcdef, 0x123);
 187.179 +    }
 187.180 +
 187.181 +    @Compare public long divideSmallNegativeNumbers() {
 187.182 +        return div(-0xabcdef, -0x123);
 187.183 +    }
 187.184 +
 187.185 +    @Compare public long divideSmallMixedNumbers() {
 187.186 +        return div(0xabcdef, -0x123);
 187.187 +    }
 187.188 +
 187.189 +    @Compare public long dividePositiveNumbersOneDigitDenom() {
 187.190 +        return div(0xabcdef0102ffffl, 0x654);
 187.191 +    }
 187.192 +
 187.193 +    @Compare public long divideNegativeNumbersOneDigitDenom() {
 187.194 +        return div(-0xabcdef0102ffffl, -0x654);
 187.195 +    }
 187.196 +
 187.197 +    @Compare public long divideMixedNumbersOneDigitDenom() {
 187.198 +        return div(-0xabcdef0102ffffl, 0x654);
 187.199 +    }
 187.200 +
 187.201 +    @Compare public long dividePositiveNumbersMultiDigitDenom() {
 187.202 +        return div(0x7ffefc003322aabbl, 0x89ab1000l);
 187.203 +    }
 187.204 +
 187.205 +    @Compare public long divideNegativeNumbersMultiDigitDenom() {
 187.206 +        return div(-0x7ffefc003322aabbl, -0x123489ab1001l);
 187.207 +    }
 187.208 +
 187.209 +    @Compare public long divideMixedNumbersMultiDigitDenom() {
 187.210 +        return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
 187.211 +    }
 187.212 +
 187.213 +    @Compare public long divideWithOverflow() {
 187.214 +        return div(0x8000fffe0000l, 0x8000ffffl);
 187.215 +    }
 187.216 +
 187.217 +    @Compare public long divideWithCorrection() {
 187.218 +        return div(0x7fff800000000000l, 0x800000000001l);
 187.219 +    }
 187.220 +
 187.221 +    @Compare public long moduloSmallPositiveNumbers() {
 187.222 +        return mod(0xabcdef, 0x123);
 187.223 +    }
 187.224 +
 187.225 +    @Compare public long moduloSmallNegativeNumbers() {
 187.226 +        return mod(-0xabcdef, -0x123);
 187.227 +    }
 187.228 +
 187.229 +    @Compare public long moduloSmallMixedNumbers() {
 187.230 +        return mod(0xabcdef, -0x123);
 187.231 +    }
 187.232 +
 187.233 +    @Compare public long moduloPositiveNumbersOneDigitDenom() {
 187.234 +        return mod(0xabcdef0102ffffl, 0x654);
 187.235 +    }
 187.236 +
 187.237 +    @Compare public long moduloNegativeNumbersOneDigitDenom() {
 187.238 +        return mod(-0xabcdef0102ffffl, -0x654);
 187.239 +    }
 187.240 +
 187.241 +    @Compare public long moduloMixedNumbersOneDigitDenom() {
 187.242 +        return mod(-0xabcdef0102ffffl, 0x654);
 187.243 +    }
 187.244 +
 187.245 +    @Compare public long moduloPositiveNumbersMultiDigitDenom() {
 187.246 +        return mod(0x7ffefc003322aabbl, 0x89ab1000l);
 187.247 +    }
 187.248 +
 187.249 +    @Compare public long moduloNegativeNumbersMultiDigitDenom() {
 187.250 +        return mod(-0x7ffefc003322aabbl, -0x123489ab1001l);
 187.251 +    }
 187.252 +
 187.253 +    @Compare public long moduloMixedNumbersMultiDigitDenom() {
 187.254 +        return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
 187.255 +    }
 187.256 +
 187.257 +    @Compare public long moduloWithOverflow() {
 187.258 +        return mod(0x8000fffe0000l, 0x8000ffffl);
 187.259 +    }
 187.260 +
 187.261 +    @Compare public long moduloWithCorrection() {
 187.262 +        return mod(0x7fff800000000000l, 0x800000000001l);
 187.263 +    }
 187.264 +
 187.265 +    @Compare public long conversionFromFloatPositive() {
 187.266 +        return (long) fadd(2, 0.6f);
 187.267 +    }
 187.268 +
 187.269 +    @Compare public long conversionFromFloatNegative() {
 187.270 +        return (long) fadd(-2, -0.6f);
 187.271 +    }
 187.272 +
 187.273 +    @Compare public long conversionFromDoublePositive() {
 187.274 +        return (long) dadd(0x20ffff0000L, 0.6);
 187.275 +    }
 187.276 +
 187.277 +    @Compare public long conversionFromDoubleNegative() {
 187.278 +        return (long) dadd(-0x20ffff0000L, -0.6);
 187.279 +    }
 187.280 +
 187.281 +    @Compare public boolean divByZeroThrowsArithmeticException() {
 187.282 +        try {
 187.283 +            div(1, 0);
 187.284 +            return false;
 187.285 +        } catch (final ArithmeticException e) {
 187.286 +            return true;
 187.287 +        }
 187.288 +    }
 187.289 +
 187.290 +    @Compare public boolean modByZeroThrowsArithmeticException() {
 187.291 +        try {
 187.292 +            mod(1, 0);
 187.293 +            return false;
 187.294 +        } catch (final ArithmeticException e) {
 187.295 +            return true;
 187.296 +        }
 187.297 +    }
 187.298 +
 187.299 +    @Compare public long shiftL1() {
 187.300 +        return shl(0x00fa37d7763e0ca1l, 5);
 187.301 +    }
 187.302 +
 187.303 +    @Compare public long shiftL2() {
 187.304 +        return shl(0x00fa37d7763e0ca1l, 32);
 187.305 +    }
 187.306 +
 187.307 +    @Compare public long shiftL3() {
 187.308 +        return shl(0x00fa37d7763e0ca1l, 45);
 187.309 +    }
 187.310 +
 187.311 +    @Compare public long shiftR1() {
 187.312 +        return shr(0x00fa37d7763e0ca1l, 5);
 187.313 +    }
 187.314 +
 187.315 +    @Compare public long shiftR2() {
 187.316 +        return shr(0x00fa37d7763e0ca1l, 32);
 187.317 +    }
 187.318 +
 187.319 +    @Compare public long shiftR3() {
 187.320 +        return shr(0x00fa37d7763e0ca1l, 45);
 187.321 +    }
 187.322 +
 187.323 +    @Compare public long uShiftR1() {
 187.324 +        return ushr(0x00fa37d7763e0ca1l, 5);
 187.325 +    }
 187.326 +
 187.327 +    @Compare public long uShiftR2() {
 187.328 +        return ushr(0x00fa37d7763e0ca1l, 45);
 187.329 +    }
 187.330 +
 187.331 +    @Compare public long uShiftR3() {
 187.332 +        return ushr(0xf0fa37d7763e0ca1l, 5);
 187.333 +    }
 187.334 +
 187.335 +    @Compare public long uShiftR4() {
 187.336 +        return ushr(0xf0fa37d7763e0ca1l, 45);
 187.337 +    }
 187.338 +
 187.339 +    @Compare public long and1() {
 187.340 +        return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 187.341 +    }
 187.342 +
 187.343 +    @Compare public long or1() {
 187.344 +        return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 187.345 +    }
 187.346 +
 187.347 +    @Compare public long xor1() {
 187.348 +        return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 187.349 +    }
 187.350 +
 187.351 +    @Compare public long xor2() {
 187.352 +        return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
 187.353 +    }
 187.354 +
 187.355 +    @Compare public long xor3() {
 187.356 +        return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
 187.357 +    }
 187.358 +
 187.359 +    @Compare public int compareSameNumbers() {
 187.360 +        return compare(0x0000000000000000l, 0x0000000000000000l, 0);
 187.361 +    }
 187.362 +
 187.363 +    @Compare public int comparePositiveNumbers() {
 187.364 +        return compare(0x0000000000200000l, 0x0000000010000000l, 0);
 187.365 +    }
 187.366 +
 187.367 +    @Compare public int compareNegativeNumbers() {
 187.368 +        return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0);
 187.369 +    }
 187.370 +
 187.371 +    @Compare public int compareMixedNumbers() {
 187.372 +        return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0);
 187.373 +    }
 187.374 +    
 187.375 +    @Factory
 187.376 +    public static Object[] create() {
 187.377 +        return VMTest.create(LongArithmeticTest.class);
 187.378 +    }
 187.379 +}
   188.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   188.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/NotifyWaitTest.java	Mon Oct 07 14:20:58 2013 +0200
   188.3 @@ -0,0 +1,62 @@
   188.4 +/**
   188.5 + * Back 2 Browser Bytecode Translator
   188.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   188.7 + *
   188.8 + * This program is free software: you can redistribute it and/or modify
   188.9 + * it under the terms of the GNU General Public License as published by
  188.10 + * the Free Software Foundation, version 2 of the License.
  188.11 + *
  188.12 + * This program is distributed in the hope that it will be useful,
  188.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  188.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  188.15 + * GNU General Public License for more details.
  188.16 + *
  188.17 + * You should have received a copy of the GNU General Public License
  188.18 + * along with this program. Look for COPYING file in the top folder.
  188.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  188.20 + */
  188.21 +package org.apidesign.bck2brwsr.tck;
  188.22 +
  188.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  188.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  188.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  188.26 +import org.testng.annotations.Factory;
  188.27 +
  188.28 +/**
  188.29 + *
  188.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  188.31 + */
  188.32 +public class NotifyWaitTest {
  188.33 +    
  188.34 +    @Compare public synchronized String canCallNotify() throws Exception {
  188.35 +        notify();
  188.36 +        return "OK";
  188.37 +    }
  188.38 +
  188.39 +    @Compare public synchronized String canCallNotifyAll() throws Exception {
  188.40 +        notifyAll();
  188.41 +        return "OK";
  188.42 +    }
  188.43 +    
  188.44 +    @BrwsrTest public synchronized String throwsInterruptedException() {
  188.45 +        try {
  188.46 +            wait();
  188.47 +            throw new IllegalStateException();
  188.48 +        } catch (InterruptedException ex) {
  188.49 +            return "OK";
  188.50 +        }
  188.51 +    }
  188.52 +
  188.53 +    @BrwsrTest public synchronized String waitMsThrowsInterruptedException() {
  188.54 +        try {
  188.55 +            wait(32);
  188.56 +            throw new IllegalStateException();
  188.57 +        } catch (InterruptedException ex) {
  188.58 +            return "OK";
  188.59 +        }
  188.60 +    }
  188.61 +    
  188.62 +    @Factory public static Object[] create() {
  188.63 +        return VMTest.create(NotifyWaitTest.class);
  188.64 +    }
  188.65 +}
   189.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   189.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java	Mon Oct 07 14:20:58 2013 +0200
   189.3 @@ -0,0 +1,161 @@
   189.4 +/**
   189.5 + * Back 2 Browser Bytecode Translator
   189.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   189.7 + *
   189.8 + * This program is free software: you can redistribute it and/or modify
   189.9 + * it under the terms of the GNU General Public License as published by
  189.10 + * the Free Software Foundation, version 2 of the License.
  189.11 + *
  189.12 + * This program is distributed in the hope that it will be useful,
  189.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  189.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  189.15 + * GNU General Public License for more details.
  189.16 + *
  189.17 + * You should have received a copy of the GNU General Public License
  189.18 + * along with this program. Look for COPYING file in the top folder.
  189.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  189.20 + */
  189.21 +package org.apidesign.bck2brwsr.tck;
  189.22 +
  189.23 +import java.lang.reflect.Array;
  189.24 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  189.25 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  189.26 +import org.apidesign.bck2brwsr.vmtest.Compare;
  189.27 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  189.28 +import org.testng.annotations.Factory;
  189.29 +
  189.30 +/**
  189.31 + *
  189.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  189.33 + */
  189.34 +public class ReflectionArrayTest {
  189.35 +    @Compare public int lengthOfStringArray() {
  189.36 +        String[] arr = (String[]) Array.newInstance(String.class, 10);
  189.37 +        return arr.length;
  189.38 +    }
  189.39 +    
  189.40 +    @Compare public int reflectiveLengthOfStringArray() {
  189.41 +        Object arr = Array.newInstance(String.class, 10);
  189.42 +        return Array.getLength(arr);
  189.43 +    }
  189.44 +
  189.45 +    @Compare public int reflectiveLengthOneNonArray() {
  189.46 +        Object arr = "non-array";
  189.47 +        return Array.getLength(arr);
  189.48 +    }
  189.49 +
  189.50 +    @Compare public String compTypeOfStringArray() {
  189.51 +        String[] arr = (String[]) Array.newInstance(String.class, 10);
  189.52 +        return arr.getClass().getComponentType().getName();
  189.53 +    }
  189.54 +
  189.55 +    @Compare public Object negativeArrayExcp() {
  189.56 +        return Array.newInstance(String.class, -5);
  189.57 +    }
  189.58 +    
  189.59 +    @Compare public int lengthOfIntArray() {
  189.60 +        int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10);
  189.61 +        return arr.length;
  189.62 +    }
  189.63 +
  189.64 +    @Compare public int reflectiveLengthOfIntArray() {
  189.65 +        Object arr = Array.newInstance(Integer.TYPE, 10);
  189.66 +        return Array.getLength(arr);
  189.67 +    }
  189.68 +
  189.69 +    @Compare public String compTypeOfIntArray() {
  189.70 +        int[] arr = (int[]) Array.newInstance(int.class, 10);
  189.71 +        return arr.getClass().getComponentType().getName();
  189.72 +    }
  189.73 +
  189.74 +    @Compare public Object intNegativeArrayExcp() {
  189.75 +        return Array.newInstance(int.class, -5);
  189.76 +    }
  189.77 +
  189.78 +    @Compare public Integer verifyAutobox() {
  189.79 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
  189.80 +        return (Integer) Array.get(arr, 0);
  189.81 +    }
  189.82 +    @Compare public String verifyObjectArray() {
  189.83 +        String[] arr = (String[]) Array.newInstance(String.class, 5);
  189.84 +        Array.set(arr, 0, "Hello");
  189.85 +        return (String) Array.get(arr, 0);
  189.86 +    }
  189.87 +    @Compare public int verifyInt() {
  189.88 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
  189.89 +        return Array.getInt(arr, 0);
  189.90 +    }
  189.91 +    @Compare public long verifyConvertToLong() {
  189.92 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
  189.93 +        return Array.getLong(arr, 0);
  189.94 +    }
  189.95 +
  189.96 +    @Compare public Object verifySetIntToObject() {
  189.97 +        try {
  189.98 +            Object[] arr = (Object[]) Array.newInstance(Object.class, 5);
  189.99 +            Array.setInt(arr, 0, 10);
 189.100 +            return Array.get(arr, 0);
 189.101 +        } catch (Exception exception) {
 189.102 +            return exception.getClass().getName();
 189.103 +        }
 189.104 +    }
 189.105 +    @Compare public long verifySetShort() {
 189.106 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
 189.107 +        Array.setShort(arr, 0, (short)10);
 189.108 +        return Array.getLong(arr, 0);
 189.109 +    }
 189.110 +    @Compare public long verifyCantSetLong() {
 189.111 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
 189.112 +        Array.setLong(arr, 0, 10);
 189.113 +        return Array.getLong(arr, 0);
 189.114 +    }
 189.115 +    @Compare public float verifyLongToFloat() {
 189.116 +        Object arr = Array.newInstance(float.class, 5);
 189.117 +        Array.setLong(arr, 0, 10);
 189.118 +        return Array.getFloat(arr, 0);
 189.119 +    }
 189.120 +
 189.121 +    @Compare public double verifyConvertToDouble() {
 189.122 +        int[] arr = (int[]) Array.newInstance(int.class, 5);
 189.123 +        return Array.getDouble(arr, 0);
 189.124 +    }
 189.125 +    
 189.126 +    @Compare public int multiIntArray() {
 189.127 +        int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3);
 189.128 +        return arr[0][1][2] + 5 + arr[2][2][0];
 189.129 +    }
 189.130 +
 189.131 +    @Compare public String multiIntArrayCompType() {
 189.132 +        return Array.newInstance(int.class, 3, 3, 3).getClass().getName();
 189.133 +    }
 189.134 +    
 189.135 +    @JavaScriptBody(args = {}, body = "return [1, 2];")
 189.136 +    private static native Object crtarr();
 189.137 +
 189.138 +    @JavaScriptBody(args = {}, body = "return new Object();")
 189.139 +    private static native Object newobj();
 189.140 +
 189.141 +    @BrwsrTest
 189.142 +    public static void toStringArray() {
 189.143 +        final Object arr = crtarr();
 189.144 +        final Object real = new Object[2];
 189.145 +        assert arr instanceof Object[] : "Any array is Java array: " + arr;
 189.146 +        assert arr.getClass() == real.getClass() : "Same classes " + arr + " and " + real.getClass();
 189.147 +        final String str = arr.toString();
 189.148 +        assert str != null;
 189.149 +        assert str.startsWith("[Ljava.lang.Object;@") : str;
 189.150 +    }
 189.151 +    
 189.152 +    @BrwsrTest
 189.153 +    public static void objectToString() {
 189.154 +        String s = newobj().toString();
 189.155 +        assert s != null : "Some string computed";
 189.156 +        assert s.startsWith("java.lang.Object@") : "Regular object toString(): " + s;
 189.157 +    }
 189.158 +
 189.159 +    
 189.160 +    @Factory
 189.161 +    public static Object[] create() {
 189.162 +        return VMTest.create(ReflectionArrayTest.class);
 189.163 +    }
 189.164 +}
   190.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   190.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Mon Oct 07 14:20:58 2013 +0200
   190.3 @@ -0,0 +1,272 @@
   190.4 +/**
   190.5 + * Back 2 Browser Bytecode Translator
   190.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   190.7 + *
   190.8 + * This program is free software: you can redistribute it and/or modify
   190.9 + * it under the terms of the GNU General Public License as published by
  190.10 + * the Free Software Foundation, version 2 of the License.
  190.11 + *
  190.12 + * This program is distributed in the hope that it will be useful,
  190.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  190.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  190.15 + * GNU General Public License for more details.
  190.16 + *
  190.17 + * You should have received a copy of the GNU General Public License
  190.18 + * along with this program. Look for COPYING file in the top folder.
  190.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  190.20 + */
  190.21 +package org.apidesign.bck2brwsr.tck;
  190.22 +
  190.23 +import java.lang.annotation.Retention;
  190.24 +import java.lang.annotation.RetentionPolicy;
  190.25 +import java.lang.reflect.Method;
  190.26 +import java.util.Arrays;
  190.27 +import java.util.Collections;
  190.28 +import java.util.List;
  190.29 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  190.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
  190.31 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  190.32 +import org.testng.annotations.Factory;
  190.33 +
  190.34 +/**
  190.35 + *
  190.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  190.37 + */
  190.38 +public class ReflectionTest {
  190.39 +    @Compare public boolean nonNullThis() {
  190.40 +        return this == null;
  190.41 +    }
  190.42 +    
  190.43 +    @Compare public String intType() {
  190.44 +        return Integer.TYPE.toString();
  190.45 +    }
  190.46 +
  190.47 +    @Compare public String voidType() throws Exception {
  190.48 +        return void.class.toString();
  190.49 +    }
  190.50 +
  190.51 +    @Compare public String longClass() {
  190.52 +        return long.class.toString();
  190.53 +    }
  190.54 +    
  190.55 +    @Compare public boolean isRunnableInterface() {
  190.56 +        return Runnable.class.isInterface();
  190.57 +    }
  190.58 +
  190.59 +    @Compare public boolean isAssignableToPrimitiveType() {
  190.60 +        return boolean.class.isAssignableFrom(Runnable.class);
  190.61 +    }
  190.62 +
  190.63 +    @Compare public boolean isAssignableFromPrimitiveType() {
  190.64 +        return Runnable.class.isAssignableFrom(boolean.class);
  190.65 +    }
  190.66 +
  190.67 +    @Compare public boolean isAssignableLongFromInt() {
  190.68 +        return long.class.isAssignableFrom(int.class);
  190.69 +    }
  190.70 +
  190.71 +    @Compare public boolean isAssignableIntFromLong() {
  190.72 +        return int.class.isAssignableFrom(long.class);
  190.73 +    }
  190.74 +
  190.75 +    @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
  190.76 +        return Runnable.class.getMethod("run").getName();
  190.77 +    }
  190.78 +    
  190.79 +    @Compare public String namesOfMethods() {
  190.80 +        StringBuilder sb = new StringBuilder();
  190.81 +        String[] arr = new String[20];
  190.82 +        int i = 0;
  190.83 +        for (Method m : StaticUse.class.getMethods()) {
  190.84 +            arr[i++] = m.getName();
  190.85 +        }
  190.86 +        for (String s : sort(arr, i)) {
  190.87 +            sb.append(s).append("\n");
  190.88 +        }
  190.89 +        return sb.toString();
  190.90 +    }
  190.91 +
  190.92 +    @Compare public String namesOfDeclaringClassesOfMethods() {
  190.93 +        StringBuilder sb = new StringBuilder();
  190.94 +        String[] arr = new String[20];
  190.95 +        int i = 0;
  190.96 +        for (Method m : StaticUse.class.getMethods()) {
  190.97 +            arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
  190.98 +        }
  190.99 +        for (String s : sort(arr, i)) {
 190.100 +            sb.append(s).append("\n");
 190.101 +        }
 190.102 +        return sb.toString();
 190.103 +    }
 190.104 +    
 190.105 +    @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
 190.106 +        StaticUse.class.getMethod("instanceMethod").invoke(null);
 190.107 +        return "should not happen";
 190.108 +    }
 190.109 +    
 190.110 +    @Compare public String classCastException() {
 190.111 +        try {
 190.112 +            Integer i = (Integer)StaticUseSub.getNonNull();
 190.113 +            return "" + i.intValue();
 190.114 +        } catch (ClassCastException ex) {
 190.115 +            return ex.getClass().getName();
 190.116 +        }
 190.117 +    }
 190.118 +
 190.119 +    @Compare public String methodThatThrowsException() throws Exception {
 190.120 +        StaticUse.class.getMethod("instanceMethod").invoke(new StaticUse());
 190.121 +        return "should not happen";
 190.122 +    }
 190.123 +
 190.124 +    @Compare public Object voidReturnType() throws Exception {
 190.125 +        return StaticUse.class.getMethod("instanceMethod").getReturnType();
 190.126 +    }
 190.127 +    
 190.128 +    @Retention(RetentionPolicy.RUNTIME)
 190.129 +    @interface Ann {
 190.130 +    }
 190.131 +    
 190.132 +    @Compare public String annoClass() throws Exception {
 190.133 +        Retention r = Ann.class.getAnnotation(Retention.class);
 190.134 +        assert r != null : "Annotation is present";
 190.135 +        assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
 190.136 +        return r.annotationType().getName();
 190.137 +    }
 190.138 +    
 190.139 +    @Compare public boolean isAnnotation() {
 190.140 +        return Ann.class.isAnnotation();
 190.141 +    }
 190.142 +    @Compare public boolean isNotAnnotation() {
 190.143 +        return String.class.isAnnotation();
 190.144 +    }
 190.145 +    @Compare public boolean isNotAnnotationEnum() {
 190.146 +        return E.class.isAnnotation();
 190.147 +    }
 190.148 +    enum E { A, B };
 190.149 +    @Compare public boolean isEnum() {
 190.150 +        return E.A.getClass().isEnum();
 190.151 +    }
 190.152 +
 190.153 +    @Compare public boolean isNotEnum() {
 190.154 +        return "".getClass().isEnum();
 190.155 +    }
 190.156 +    
 190.157 +    @Compare public String newInstanceFails() throws InstantiationException {
 190.158 +        try {
 190.159 +            return "success: " + StaticUseSub.class.newInstance();
 190.160 +        } catch (IllegalAccessException ex) {
 190.161 +            return ex.getClass().getName();
 190.162 +        }
 190.163 +    }
 190.164 +    
 190.165 +    @Compare public String paramTypes() throws Exception {
 190.166 +        Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
 190.167 +        final Class[] pt = plus.getParameterTypes();
 190.168 +        return pt[0].getName();
 190.169 +    }
 190.170 +    @Compare public String paramTypesNotFound() throws Exception {
 190.171 +        return StaticUse.class.getMethod("plus", int.class, double.class).toString();
 190.172 +    }
 190.173 +    @Compare public int methodWithArgs() throws Exception {
 190.174 +        Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
 190.175 +        return (Integer)plus.invoke(null, 2, 3);
 190.176 +    }
 190.177 +    
 190.178 +    @Compare public String classGetNameForByte() {
 190.179 +         return byte.class.getName();
 190.180 +    }
 190.181 +    @Compare public String classGetNameForBaseObject() {
 190.182 +        return newObject().getClass().getName();
 190.183 +    }
 190.184 +    @Compare public String classGetNameForJavaObject() {
 190.185 +        return new Object().getClass().getName();
 190.186 +    }
 190.187 +    @Compare public String classGetNameForObjectArray() {
 190.188 +        return (new Object[3]).getClass().getName();
 190.189 +    }
 190.190 +    @Compare public String classGetNameForSimpleIntArray() {
 190.191 +        return (new int[3]).getClass().getName();
 190.192 +    }
 190.193 +    @Compare public boolean sameClassGetNameForSimpleCharArray() {
 190.194 +        return (new char[3]).getClass() == (new char[34]).getClass();
 190.195 +    }
 190.196 +    @Compare public String classGetNameForMultiIntArray() {
 190.197 +        return (new int[3][4][5][6][7][8][9]).getClass().getName();
 190.198 +    }
 190.199 +    @Compare public String classGetNameForMultiIntArrayInner() {
 190.200 +        final int[][][][][][][] arr = new int[3][4][5][6][7][8][9];
 190.201 +        int[][][][][][] subarr = arr[0];
 190.202 +        int[][][][][] subsubarr = subarr[0];
 190.203 +        return subsubarr.getClass().getName();
 190.204 +    }
 190.205 +    @Compare public String classGetNameForMultiStringArray() {
 190.206 +        return (new String[3][4][5][6][7][8][9]).getClass().getName();
 190.207 +    }
 190.208 +    
 190.209 +    @Compare public String classForByte() throws Exception {
 190.210 +        return Class.forName("[Z").getName();
 190.211 +    }
 190.212 +
 190.213 +    @Compare public String classForUnknownArray() {
 190.214 +        try {
 190.215 +            return Class.forName("[W").getName();
 190.216 +        } catch (Exception ex) {
 190.217 +            return ex.getClass().getName();
 190.218 +        }
 190.219 +    }
 190.220 +    
 190.221 +    @Compare public String classForUnknownDeepArray() {
 190.222 +        try {
 190.223 +            return Class.forName("[[[[[W").getName();
 190.224 +        } catch (Exception ex) {
 190.225 +            return ex.getClass().getName();
 190.226 +        }
 190.227 +    }
 190.228 +    
 190.229 +    @Compare public String componentGetNameForObjectArray() {
 190.230 +        return (new Object[3]).getClass().getComponentType().getName();
 190.231 +    }
 190.232 +    @Compare public boolean sameComponentGetNameForObjectArray() {
 190.233 +        return (new Object[3]).getClass().getComponentType() == Object.class;
 190.234 +    }
 190.235 +    @Compare public String componentGetNameForSimpleIntArray() {
 190.236 +        return (new int[3]).getClass().getComponentType().getName();
 190.237 +    }
 190.238 +    @Compare public String componentGetNameForMultiIntArray() {
 190.239 +        return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName();
 190.240 +    }
 190.241 +    @Compare public String componentGetNameForMultiStringArray() {
 190.242 +        Class<?> c = (new String[3][4][5][6][7][8][9]).getClass();
 190.243 +        StringBuilder sb = new StringBuilder();
 190.244 +        for (;;) {
 190.245 +            sb.append(c.getName()).append("\n");
 190.246 +            c = c.getComponentType();
 190.247 +            if (c == null) {
 190.248 +                break;
 190.249 +            }
 190.250 +        }
 190.251 +        return sb.toString();
 190.252 +    }
 190.253 +    
 190.254 +    @Compare public boolean isArray() {
 190.255 +        return new Object[0].getClass().isArray();
 190.256 +    }
 190.257 +    
 190.258 +    @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;")
 190.259 +    private static String[] sort(String[] arr, int len) {
 190.260 +        List<String> list = Arrays.asList(arr).subList(0, len);
 190.261 +        Collections.sort(list);
 190.262 +        return list.toArray(new String[0]);
 190.263 +    }
 190.264 +    
 190.265 +    @JavaScriptBody(args = {}, body = "return new Object();")
 190.266 +    private static Object newObject() {
 190.267 +        return new Object();
 190.268 +    }
 190.269 +    
 190.270 +    @Factory
 190.271 +    public static Object[] create() {
 190.272 +        return VMTest.create(ReflectionTest.class);
 190.273 +    }
 190.274 +    
 190.275 +}
   191.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   191.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/RegExpSplitTest.java	Mon Oct 07 14:20:58 2013 +0200
   191.3 @@ -0,0 +1,50 @@
   191.4 +/**
   191.5 + * Back 2 Browser Bytecode Translator
   191.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   191.7 + *
   191.8 + * This program is free software: you can redistribute it and/or modify
   191.9 + * it under the terms of the GNU General Public License as published by
  191.10 + * the Free Software Foundation, version 2 of the License.
  191.11 + *
  191.12 + * This program is distributed in the hope that it will be useful,
  191.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  191.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  191.15 + * GNU General Public License for more details.
  191.16 + *
  191.17 + * You should have received a copy of the GNU General Public License
  191.18 + * along with this program. Look for COPYING file in the top folder.
  191.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  191.20 + */
  191.21 +package org.apidesign.bck2brwsr.tck;
  191.22 +
  191.23 +import java.util.Arrays;
  191.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  191.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  191.26 +import org.testng.annotations.Factory;
  191.27 +
  191.28 +/**
  191.29 + *
  191.30 + * @author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
  191.31 + */
  191.32 +public class RegExpSplitTest {
  191.33 +
  191.34 +    public @Compare Object splitSpace() {
  191.35 +        return Arrays.asList("How are you today?".split(" "));
  191.36 +    }
  191.37 +
  191.38 +    public @Compare Object splitSpaceTrimMinusOne() {
  191.39 +        return Arrays.asList(" How are you today? ".split(" ", -1));
  191.40 +    }
  191.41 +
  191.42 +    public @Compare Object splitSpaceTrimZero() {
  191.43 +        return Arrays.asList(" How are you today? ".split(" ", 0));
  191.44 +    }
  191.45 +
  191.46 +    public @Compare Object splitSpaceLimit2() {
  191.47 +        return Arrays.asList("How are you today?".split(" ", 2));
  191.48 +    }
  191.49 +    
  191.50 +    @Factory public static Object[] create() {
  191.51 +        return VMTest.create(RegExpSplitTest.class);
  191.52 +    }
  191.53 +}
   192.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   192.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java	Mon Oct 07 14:20:58 2013 +0200
   192.3 @@ -0,0 +1,45 @@
   192.4 +/**
   192.5 + * Back 2 Browser Bytecode Translator
   192.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   192.7 + *
   192.8 + * This program is free software: you can redistribute it and/or modify
   192.9 + * it under the terms of the GNU General Public License as published by
  192.10 + * the Free Software Foundation, version 2 of the License.
  192.11 + *
  192.12 + * This program is distributed in the hope that it will be useful,
  192.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  192.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  192.15 + * GNU General Public License for more details.
  192.16 + *
  192.17 + * You should have received a copy of the GNU General Public License
  192.18 + * along with this program. Look for COPYING file in the top folder.
  192.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  192.20 + */
  192.21 +package org.apidesign.bck2brwsr.tck;
  192.22 +
  192.23 +import java.io.InputStream;
  192.24 +import org.apidesign.bck2brwsr.vmtest.Compare;
  192.25 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  192.26 +import org.testng.annotations.Factory;
  192.27 +
  192.28 +/**
  192.29 + *
  192.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  192.31 + */
  192.32 +public class ResourcesTest {
  192.33 +    
  192.34 +    @Compare public String readResourceAsStream() throws Exception {
  192.35 +        InputStream is = getClass().getResourceAsStream("Resources.txt");
  192.36 +        byte[] b = new byte[30];
  192.37 +        int len = is.read(b);
  192.38 +        StringBuilder sb = new StringBuilder();
  192.39 +        for (int i = 0; i < len; i++) {
  192.40 +            sb.append((char)b[i]);
  192.41 +        }
  192.42 +        return sb.toString();
  192.43 +    }
  192.44 +    
  192.45 +    @Factory public static Object[] create() {
  192.46 +        return VMTest.create(ResourcesTest.class);
  192.47 +    }
  192.48 +}
   193.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   193.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java	Mon Oct 07 14:20:58 2013 +0200
   193.3 @@ -0,0 +1,102 @@
   193.4 +/**
   193.5 + * Back 2 Browser Bytecode Translator
   193.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   193.7 + *
   193.8 + * This program is free software: you can redistribute it and/or modify
   193.9 + * it under the terms of the GNU General Public License as published by
  193.10 + * the Free Software Foundation, version 2 of the License.
  193.11 + *
  193.12 + * This program is distributed in the hope that it will be useful,
  193.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  193.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  193.15 + * GNU General Public License for more details.
  193.16 + *
  193.17 + * You should have received a copy of the GNU General Public License
  193.18 + * along with this program. Look for COPYING file in the top folder.
  193.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  193.20 + */
  193.21 +package org.apidesign.bck2brwsr.tck;
  193.22 +
  193.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  193.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  193.25 +import org.testng.annotations.Factory;
  193.26 +
  193.27 +/**
  193.28 + *
  193.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  193.30 + */
  193.31 +public class ShortArithmeticTest {
  193.32 +    
  193.33 +    private static short add(short x, short y) {
  193.34 +        return (short)(x + y);
  193.35 +    }
  193.36 +    
  193.37 +    private static short sub(short x, short y) {
  193.38 +        return (short)(x - y);
  193.39 +    }
  193.40 +    
  193.41 +    private static short mul(short x, short y) {
  193.42 +        return (short)(x * y);
  193.43 +    }
  193.44 +    
  193.45 +    private static short div(short x, short y) {
  193.46 +        return (short)(x / y);
  193.47 +    }
  193.48 +    
  193.49 +    private static short mod(short x, short y) {
  193.50 +        return (short)(x % y);
  193.51 +    }
  193.52 +    
  193.53 +    @Compare public short conversion() {
  193.54 +        return (short)123456;
  193.55 +    }
  193.56 +    
  193.57 +    @Compare public short addOverflow() {
  193.58 +        return add(Short.MAX_VALUE, (short)1);
  193.59 +    }
  193.60 +    
  193.61 +    @Compare public short subUnderflow() {
  193.62 +        return sub(Short.MIN_VALUE, (short)1);
  193.63 +    }
  193.64 +    
  193.65 +    @Compare public short addMaxShortAndMaxShort() {
  193.66 +        return add(Short.MAX_VALUE, Short.MAX_VALUE);
  193.67 +    }
  193.68 +    
  193.69 +    @Compare public short subMinShortAndMinShort() {
  193.70 +        return sub(Short.MIN_VALUE, Short.MIN_VALUE);
  193.71 +    }
  193.72 +    
  193.73 +    @Compare public short multiplyMaxShort() {
  193.74 +        return mul(Short.MAX_VALUE, (short)2);
  193.75 +    }
  193.76 +    
  193.77 +    @Compare public short multiplyMaxShortAndMaxShort() {
  193.78 +        return mul(Short.MAX_VALUE, Short.MAX_VALUE);
  193.79 +    }
  193.80 +    
  193.81 +    @Compare public short multiplyMinShort() {
  193.82 +        return mul(Short.MIN_VALUE, (short)2);
  193.83 +    }
  193.84 +    
  193.85 +    @Compare public short multiplyMinShortAndMinShort() {
  193.86 +        return mul(Short.MIN_VALUE, Short.MIN_VALUE);
  193.87 +    }
  193.88 +    
  193.89 +    @Compare public short multiplyPrecision() {
  193.90 +        return mul((short)17638, (short)1103);
  193.91 +    }
  193.92 +    
  193.93 +    @Compare public short division() {
  193.94 +        return div((short)1, (short)2);
  193.95 +    }
  193.96 +    
  193.97 +    @Compare public short divisionReminder() {
  193.98 +        return mod((short)1, (short)2);
  193.99 +    }
 193.100 +    
 193.101 +    @Factory
 193.102 +    public static Object[] create() {
 193.103 +        return VMTest.create(ShortArithmeticTest.class);
 193.104 +    }
 193.105 +}
   194.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   194.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java	Mon Oct 07 14:20:58 2013 +0200
   194.3 @@ -0,0 +1,39 @@
   194.4 +/**
   194.5 + * Back 2 Browser Bytecode Translator
   194.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   194.7 + *
   194.8 + * This program is free software: you can redistribute it and/or modify
   194.9 + * it under the terms of the GNU General Public License as published by
  194.10 + * the Free Software Foundation, version 2 of the License.
  194.11 + *
  194.12 + * This program is distributed in the hope that it will be useful,
  194.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  194.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  194.15 + * GNU General Public License for more details.
  194.16 + *
  194.17 + * You should have received a copy of the GNU General Public License
  194.18 + * along with this program. Look for COPYING file in the top folder.
  194.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  194.20 + */
  194.21 +package org.apidesign.bck2brwsr.tck;
  194.22 +
  194.23 +class StaticUse {
  194.24 +    public static final Object NON_NULL = new Object();
  194.25 +    public static int cnt;
  194.26 +    static {
  194.27 +        if (cnt++ != 0) {
  194.28 +            throw new IllegalStateException("Multiple initialization of a <cinit>");
  194.29 +        }
  194.30 +    }
  194.31 +    
  194.32 +    StaticUse() {
  194.33 +    }
  194.34 +    
  194.35 +    public void instanceMethod() {
  194.36 +        throw new IllegalStateException();
  194.37 +    }
  194.38 +
  194.39 +    public static int plus(int a, int b) {
  194.40 +        return a + b;
  194.41 +    }
  194.42 +}
   195.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   195.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSub.java	Mon Oct 07 14:20:58 2013 +0200
   195.3 @@ -0,0 +1,30 @@
   195.4 +/**
   195.5 + * Back 2 Browser Bytecode Translator
   195.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   195.7 + *
   195.8 + * This program is free software: you can redistribute it and/or modify
   195.9 + * it under the terms of the GNU General Public License as published by
  195.10 + * the Free Software Foundation, version 2 of the License.
  195.11 + *
  195.12 + * This program is distributed in the hope that it will be useful,
  195.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  195.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  195.15 + * GNU General Public License for more details.
  195.16 + *
  195.17 + * You should have received a copy of the GNU General Public License
  195.18 + * along with this program. Look for COPYING file in the top folder.
  195.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  195.20 + */
  195.21 +package org.apidesign.bck2brwsr.tck;
  195.22 +
  195.23 +public class StaticUseSub extends StaticUse {
  195.24 +    private StaticUseSub() {
  195.25 +    }
  195.26 +    
  195.27 +    public static Object getNonNull() {
  195.28 +        return NON_NULL;
  195.29 +    }
  195.30 +    static Object getNull() {
  195.31 +        return null;
  195.32 +    }
  195.33 +}
   196.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   196.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/tck/StaticUseSubTest.java	Mon Oct 07 14:20:58 2013 +0200
   196.3 @@ -0,0 +1,45 @@
   196.4 +/**
   196.5 + * Back 2 Browser Bytecode Translator
   196.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   196.7 + *
   196.8 + * This program is free software: you can redistribute it and/or modify
   196.9 + * it under the terms of the GNU General Public License as published by
  196.10 + * the Free Software Foundation, version 2 of the License.
  196.11 + *
  196.12 + * This program is distributed in the hope that it will be useful,
  196.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  196.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  196.15 + * GNU General Public License for more details.
  196.16 + *
  196.17 + * You should have received a copy of the GNU General Public License
  196.18 + * along with this program. Look for COPYING file in the top folder.
  196.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  196.20 + */
  196.21 +package org.apidesign.bck2brwsr.tck;
  196.22 +
  196.23 +import org.apidesign.bck2brwsr.vmtest.Compare;
  196.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  196.25 +import org.testng.annotations.Factory;
  196.26 +
  196.27 +/**
  196.28 + *
  196.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  196.30 + */
  196.31 +public class StaticUseSubTest {
  196.32 +    @Compare public String staticFieldInitializationInSuperClass() throws Exception {
  196.33 +        Object ret = StaticUseSub.getNonNull();
  196.34 +        return ret.getClass().getName();
  196.35 +    }
  196.36 +    
  196.37 +    @Compare public String isNullPointerTheSame() throws Exception {
  196.38 +        try {
  196.39 +            return StaticUseSub.getNull().getClass().toString();
  196.40 +        } catch (NullPointerException ex) {
  196.41 +            return ex.getClass().getName();
  196.42 +        }
  196.43 +    }
  196.44 +
  196.45 +    @Factory public static Object[] create() {
  196.46 +        return VMTest.create(StaticUseSubTest.class);
  196.47 +    }
  196.48 +}
   197.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   197.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java	Mon Oct 07 14:20:58 2013 +0200
   197.3 @@ -0,0 +1,41 @@
   197.4 +/**
   197.5 + * Back 2 Browser Bytecode Translator
   197.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   197.7 + *
   197.8 + * This program is free software: you can redistribute it and/or modify
   197.9 + * it under the terms of the GNU General Public License as published by
  197.10 + * the Free Software Foundation, version 2 of the License.
  197.11 + *
  197.12 + * This program is distributed in the hope that it will be useful,
  197.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  197.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  197.15 + * GNU General Public License for more details.
  197.16 + *
  197.17 + * You should have received a copy of the GNU General Public License
  197.18 + * along with this program. Look for COPYING file in the top folder.
  197.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  197.20 + */
  197.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  197.22 +
  197.23 +import java.io.UnsupportedEncodingException;
  197.24 +import java.util.zip.CRC32;
  197.25 +import org.apidesign.bck2brwsr.vmtest.Compare;
  197.26 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  197.27 +import org.testng.annotations.Factory;
  197.28 +
  197.29 +/**
  197.30 + *
  197.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  197.32 + */
  197.33 +public class CRC32Test {
  197.34 +
  197.35 +    @Compare public long crc1() throws UnsupportedEncodingException {
  197.36 +        CRC32 crc = new CRC32();
  197.37 +        crc.update("Hello World!".getBytes("UTF-8"));
  197.38 +        return crc.getValue();
  197.39 +    }
  197.40 +    
  197.41 +    @Factory public static Object[] create() {
  197.42 +        return VMTest.create(CRC32Test.class);
  197.43 +    }
  197.44 +}
   198.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   198.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CallMeTwiceTest.java	Mon Oct 07 14:20:58 2013 +0200
   198.3 @@ -0,0 +1,43 @@
   198.4 +/**
   198.5 + * Back 2 Browser Bytecode Translator
   198.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   198.7 + *
   198.8 + * This program is free software: you can redistribute it and/or modify
   198.9 + * it under the terms of the GNU General Public License as published by
  198.10 + * the Free Software Foundation, version 2 of the License.
  198.11 + *
  198.12 + * This program is distributed in the hope that it will be useful,
  198.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  198.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  198.15 + * GNU General Public License for more details.
  198.16 + *
  198.17 + * You should have received a copy of the GNU General Public License
  198.18 + * along with this program. Look for COPYING file in the top folder.
  198.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  198.20 + */
  198.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  198.22 +
  198.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  198.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  198.25 +import org.testng.annotations.Factory;
  198.26 +
  198.27 +/**
  198.28 + *
  198.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  198.30 + */
  198.31 +public class CallMeTwiceTest {
  198.32 +    int cnt;
  198.33 +    
  198.34 +    @BrwsrTest public void callMeTwice() throws InterruptedException {
  198.35 +        if (cnt++ == 0) {
  198.36 +            throw new InterruptedException();
  198.37 +        }
  198.38 +        int prevCnt = cnt;
  198.39 +        cnt = 0;
  198.40 +        assert prevCnt == 2 : "We need to receive two calls " + prevCnt;
  198.41 +    }
  198.42 +    
  198.43 +    @Factory public static Object[] create() {
  198.44 +        return VMTest.create(CallMeTwiceTest.class);
  198.45 +    }
  198.46 +}
   199.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   199.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/HtmlAnnotations.java	Mon Oct 07 14:20:58 2013 +0200
   199.3 @@ -0,0 +1,86 @@
   199.4 +/**
   199.5 + * Back 2 Browser Bytecode Translator
   199.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   199.7 + *
   199.8 + * This program is free software: you can redistribute it and/or modify
   199.9 + * it under the terms of the GNU General Public License as published by
  199.10 + * the Free Software Foundation, version 2 of the License.
  199.11 + *
  199.12 + * This program is distributed in the hope that it will be useful,
  199.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  199.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  199.15 + * GNU General Public License for more details.
  199.16 + *
  199.17 + * You should have received a copy of the GNU General Public License
  199.18 + * along with this program. Look for COPYING file in the top folder.
  199.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  199.20 + */
  199.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  199.22 +
  199.23 +import net.java.html.js.JavaScriptBody;
  199.24 +import net.java.html.js.JavaScriptResource;
  199.25 +
  199.26 +/**
  199.27 + *
  199.28 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  199.29 + */
  199.30 +@JavaScriptResource("htmlannotations.js")
  199.31 +public class HtmlAnnotations {
  199.32 +    private Object callback;
  199.33 +    
  199.34 +    
  199.35 +    @JavaScriptBody(args = {}, body = "return 42;")
  199.36 +    public static int fourtyTwo() {
  199.37 +        return -1;
  199.38 +    }
  199.39 +    
  199.40 +    @JavaScriptBody(args = { "x", "y" }, body = "return mul(x, y);")
  199.41 +    public static native int useExternalMul(int x, int y);
  199.42 +    
  199.43 +    public static int callback() {
  199.44 +        final int[] arr = { 0 };
  199.45 +        callback(new Runnable() {
  199.46 +            @Override
  199.47 +            public void run() {
  199.48 +                arr[0]++;
  199.49 +            }
  199.50 +        });
  199.51 +        return arr[0];
  199.52 +    }
  199.53 +    
  199.54 +    @JavaScriptBody(args = { "r" }, javacall=true, body = "r.@java.lang.Runnable::run()()")
  199.55 +    private static native void callback(Runnable r);
  199.56 +
  199.57 +    @JavaScriptBody(args = {  }, javacall = true, body = "return @org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::callback()();")
  199.58 +    public static native int staticCallback();
  199.59 +    
  199.60 +    
  199.61 +    protected long chooseLong(boolean takeFirst, boolean takeSecond, long first, long second) {
  199.62 +        long l = 0;
  199.63 +        if (takeFirst) l += first;
  199.64 +        if (takeSecond) l += second;
  199.65 +        return l;
  199.66 +    }
  199.67 +    
  199.68 +    protected void onError(Object obj) throws Exception {
  199.69 +        callback = obj;
  199.70 +    }
  199.71 +    
  199.72 +    Object getError() {
  199.73 +        return callback;
  199.74 +    }
  199.75 +    
  199.76 +    public static Object create() {
  199.77 +        return new HtmlAnnotations();
  199.78 +    }
  199.79 +    @JavaScriptBody(args = { "impl", "a", "b" }, javacall = true, body = 
  199.80 +        "return impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::chooseLong(ZZJJ)(true, false, a, b);"
  199.81 +    )
  199.82 +    public static native long first(Object impl, long a, long b);
  199.83 +    
  199.84 +    @JavaScriptBody(args = { "impl", "d" }, javacall = true, body = 
  199.85 +        "impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::onError(Ljava/lang/Object;)(d);" +
  199.86 +        "return impl.@org.apidesign.bck2brwsr.vmtest.impl.HtmlAnnotations::getError()();"
  199.87 +    )
  199.88 +    public static native Double onError(Object impl, Double d);
  199.89 +}
   200.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   200.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/HtmlAnnotationsTest.java	Mon Oct 07 14:20:58 2013 +0200
   200.3 @@ -0,0 +1,71 @@
   200.4 +/**
   200.5 + * Back 2 Browser Bytecode Translator
   200.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   200.7 + *
   200.8 + * This program is free software: you can redistribute it and/or modify
   200.9 + * it under the terms of the GNU General Public License as published by
  200.10 + * the Free Software Foundation, version 2 of the License.
  200.11 + *
  200.12 + * This program is distributed in the hope that it will be useful,
  200.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  200.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  200.15 + * GNU General Public License for more details.
  200.16 + *
  200.17 + * You should have received a copy of the GNU General Public License
  200.18 + * along with this program. Look for COPYING file in the top folder.
  200.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  200.20 + */
  200.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  200.22 +
  200.23 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  200.24 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  200.25 +import org.testng.annotations.Factory;
  200.26 +
  200.27 +/** Verify cooperation with net.java.html.js annotations.
  200.28 + *
  200.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  200.30 + */
  200.31 +public class HtmlAnnotationsTest {
  200.32 +    @BrwsrTest public void fourtyTwo() throws Exception {
  200.33 +        assertEquals(HtmlAnnotations.fourtyTwo(), 42);
  200.34 +    }
  200.35 +    
  200.36 +    @BrwsrTest public void externalMul() throws Exception {
  200.37 +        assertEquals(HtmlAnnotations.useExternalMul(7, 6), 42);
  200.38 +    }
  200.39 +
  200.40 +    @BrwsrTest public void callRunnableFromJS() throws Exception {
  200.41 +        assertEquals(HtmlAnnotations.callback(), 1);
  200.42 +    }
  200.43 +
  200.44 +    @BrwsrTest public void callStaticMethodFromJS() throws Exception {
  200.45 +        assertEquals(HtmlAnnotations.staticCallback(), 1);
  200.46 +    }
  200.47 +
  200.48 +    @BrwsrTest public void callbackWithFourParamsAndReturnType() throws Exception {
  200.49 +        Object instance = HtmlAnnotations.create();
  200.50 +        assertNotNull(instance, "Instance created");
  200.51 +        assertEquals(HtmlAnnotations.first(instance, 42, 31), 42);
  200.52 +    }
  200.53 +
  200.54 +    @BrwsrTest public void callbackWithObjectParamsAndReturnType() throws Exception {
  200.55 +        Object instance = HtmlAnnotations.create();
  200.56 +        assertNotNull(instance, "Instance created");
  200.57 +        assertEquals(HtmlAnnotations.onError(instance, 42.0), 42.0);
  200.58 +    }
  200.59 +    
  200.60 +    private static void assertEquals(double real, double exp) {
  200.61 +        if (real - exp < 0.01) {
  200.62 +            return;
  200.63 +        }
  200.64 +        assert false : "Expecting " + exp + " but was " + real;
  200.65 +    }
  200.66 +
  200.67 +    private static void assertNotNull(Object obj, String msg) {
  200.68 +        assert obj != null : msg;
  200.69 +    }
  200.70 +    
  200.71 +    @Factory public static Object[] create() {
  200.72 +        return VMTest.create(HtmlAnnotationsTest.class);
  200.73 +    }
  200.74 +}
   201.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   201.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java	Mon Oct 07 14:20:58 2013 +0200
   201.3 @@ -0,0 +1,67 @@
   201.4 +/**
   201.5 + * Back 2 Browser Bytecode Translator
   201.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   201.7 + *
   201.8 + * This program is free software: you can redistribute it and/or modify
   201.9 + * it under the terms of the GNU General Public License as published by
  201.10 + * the Free Software Foundation, version 2 of the License.
  201.11 + *
  201.12 + * This program is distributed in the hope that it will be useful,
  201.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  201.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  201.15 + * GNU General Public License for more details.
  201.16 + *
  201.17 + * You should have received a copy of the GNU General Public License
  201.18 + * along with this program. Look for COPYING file in the top folder.
  201.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  201.20 + */
  201.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  201.22 +
  201.23 +import java.io.ByteArrayInputStream;
  201.24 +import java.io.IOException;
  201.25 +import java.io.InputStream;
  201.26 +import org.apidesign.bck2brwsr.emul.zip.FastJar;
  201.27 +import org.testng.annotations.Test;
  201.28 +import static org.testng.Assert.*;
  201.29 +
  201.30 +/**
  201.31 + *
  201.32 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  201.33 + */
  201.34 +@GenerateZip(name = "five.zip", contents = {
  201.35 +    "1.txt", "one",
  201.36 +    "2.txt", "duo",
  201.37 +    "3.txt", "three",
  201.38 +    "4.txt", "four",
  201.39 +    "5.txt", "five"
  201.40 +})
  201.41 +public class ZipEntryTest {
  201.42 +    @Test
  201.43 +    public void readEntriesEffectively() throws IOException {
  201.44 +        InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
  201.45 +        byte[] arr = new byte[is.available()];
  201.46 +        int len = is.read(arr);
  201.47 +        assertEquals(len, arr.length, "Read fully");
  201.48 +        
  201.49 +        FastJar fj = new FastJar(arr);
  201.50 +        FastJar.Entry[] entrs = fj.list();
  201.51 +        
  201.52 +        assertEquals(5, entrs.length, "Five entries");
  201.53 +        
  201.54 +        for (int i = 1; i <= 5; i++) {
  201.55 +            FastJar.Entry en = entrs[i - 1];
  201.56 +            assertEquals(en.name, i + ".txt");
  201.57 +//            assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
  201.58 +        }
  201.59 +        
  201.60 +        assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
  201.61 +        assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
  201.62 +    }
  201.63 +
  201.64 +    private static void assertContent(String exp, InputStream is, String msg) throws IOException {
  201.65 +        byte[] arr = new byte[512];
  201.66 +        int len = is.read(arr);
  201.67 +        String s = new String(arr, 0, len);
  201.68 +        assertEquals(exp, s, msg);
  201.69 +    }
  201.70 +}
   202.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   202.2 +++ b/rt/emul/compact/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Mon Oct 07 14:20:58 2013 +0200
   202.3 @@ -0,0 +1,108 @@
   202.4 +/**
   202.5 + * Back 2 Browser Bytecode Translator
   202.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   202.7 + *
   202.8 + * This program is free software: you can redistribute it and/or modify
   202.9 + * it under the terms of the GNU General Public License as published by
  202.10 + * the Free Software Foundation, version 2 of the License.
  202.11 + *
  202.12 + * This program is distributed in the hope that it will be useful,
  202.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  202.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  202.15 + * GNU General Public License for more details.
  202.16 + *
  202.17 + * You should have received a copy of the GNU General Public License
  202.18 + * along with this program. Look for COPYING file in the top folder.
  202.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  202.20 + */
  202.21 +package org.apidesign.bck2brwsr.vmtest.impl;
  202.22 +
  202.23 +import java.io.IOException;
  202.24 +import java.io.InputStream;
  202.25 +import java.util.Objects;
  202.26 +import java.util.zip.ZipEntry;
  202.27 +import java.util.zip.ZipInputStream;
  202.28 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  202.29 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  202.30 +import org.apidesign.bck2brwsr.vmtest.Compare;
  202.31 +import org.apidesign.bck2brwsr.vmtest.Http;
  202.32 +import org.apidesign.bck2brwsr.vmtest.VMTest;
  202.33 +import org.testng.annotations.Factory;
  202.34 +
  202.35 +/**
  202.36 + *
  202.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  202.38 + */
  202.39 +@GenerateZip(name = "readAnEntry.zip", contents = { 
  202.40 +    "my/main/file.txt", "Hello World!"
  202.41 +})
  202.42 +public class ZipFileTest {
  202.43 +    
  202.44 +    @Compare public String readAnEntry() throws IOException {
  202.45 +        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
  202.46 +        ZipInputStream zip = new ZipInputStream(is);
  202.47 +        ZipEntry entry = zip.getNextEntry();
  202.48 +        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
  202.49 +
  202.50 +        byte[] arr = new byte[4096];
  202.51 +        int len = zip.read(arr);
  202.52 +        
  202.53 +        assertEquals(zip.getNextEntry(), null, "No next entry");
  202.54 +        
  202.55 +        final String ret = new String(arr, 0, len, "UTF-8");
  202.56 +        return ret;
  202.57 +    }
  202.58 +    
  202.59 +    @JavaScriptBody(args = { "res", "path" }, body = 
  202.60 +          "var myvm = bck2brwsr.apply(null, path);\n"
  202.61 +        + "var cls = myvm.loadClass('java.lang.String');\n"
  202.62 +        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
  202.63 +    )
  202.64 +    private static native Object loadVMResource(String res, String...path);
  202.65 +
  202.66 +    @Http({
  202.67 +        @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
  202.68 +    })
  202.69 +    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
  202.70 +        Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
  202.71 +        assert res instanceof InputStream : "Got array of bytes: " + res;
  202.72 +        InputStream is = (InputStream)res;
  202.73 +        
  202.74 +        byte[] arr = new byte[4096];
  202.75 +        int len = is.read(arr);
  202.76 +        
  202.77 +        final String ret = new String(arr, 0, len, "UTF-8");
  202.78 +
  202.79 +        assertEquals(ret, "Hello World!", "Can read the bytes");
  202.80 +    }
  202.81 +    
  202.82 +    @GenerateZip(name = "cpattr.zip", contents = { 
  202.83 +        "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
  202.84 +        + "Created-By: hand\n"
  202.85 +        + "Class-Path: realJar.jar\n\n\n"
  202.86 +    })
  202.87 +    @Http({
  202.88 +        @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
  202.89 +        @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
  202.90 +    })
  202.91 +    @BrwsrTest  public void understandsClassPathAttr() throws IOException {
  202.92 +        Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
  202.93 +        assert res instanceof InputStream : "Got array of bytes: " + res;
  202.94 +        InputStream is = (InputStream)res;
  202.95 +        
  202.96 +        byte[] arr = new byte[4096];
  202.97 +        int len = is.read(arr);
  202.98 +        
  202.99 +        final String ret = new String(arr, 0, len, "UTF-8");
 202.100 +
 202.101 +        assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
 202.102 +    }
 202.103 +    
 202.104 +    private static void assertEquals(Object real, Object exp, String msg) {
 202.105 +        assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
 202.106 +    }
 202.107 +    
 202.108 +    @Factory public static Object[] create() {
 202.109 +        return VMTest.create(ZipFileTest.class);
 202.110 +    }
 202.111 +}
   203.1 Binary file rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-0.3-SNAPSHOT.jar has changed
   204.1 Binary file rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/compact/tck/demo.static.calculator-TEST.jar has changed
   205.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   205.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe	Mon Oct 07 14:20:58 2013 +0200
   205.3 @@ -0,0 +1,1 @@
   205.4   205.5 \ No newline at end of file
   206.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   206.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt	Mon Oct 07 14:20:58 2013 +0200
   206.3 @@ -0,0 +1,1 @@
   206.4 +Ahoj
   207.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   207.2 +++ b/rt/emul/compact/src/test/resources/org/apidesign/bck2brwsr/vmtest/impl/htmlannotations.js	Mon Oct 07 14:20:58 2013 +0200
   207.3 @@ -0,0 +1,20 @@
   207.4 +/*
   207.5 + * Back 2 Browser Bytecode Translator
   207.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   207.7 + *
   207.8 + * This program is free software: you can redistribute it and/or modify
   207.9 + * it under the terms of the GNU General Public License as published by
  207.10 + * the Free Software Foundation, version 2 of the License.
  207.11 + *
  207.12 + * This program is distributed in the hope that it will be useful,
  207.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  207.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  207.15 + * GNU General Public License for more details.
  207.16 + *
  207.17 + * You should have received a copy of the GNU General Public License
  207.18 + * along with this program. Look for COPYING file in the top folder.
  207.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  207.20 + */
  207.21 +
  207.22 +function mul(x, y) { return x * y; }
  207.23 +window.mul = mul;
   208.1 --- a/rt/emul/mini/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   208.2 +++ b/rt/emul/mini/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   208.3 @@ -1,15 +1,14 @@
   208.4  <?xml version="1.0"?>
   208.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   208.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   208.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   208.8    <modelVersion>4.0.0</modelVersion>
   208.9    <parent>
  208.10      <groupId>org.apidesign.bck2brwsr</groupId>
  208.11      <artifactId>emul.pom</artifactId>
  208.12 -    <version>0.3-SNAPSHOT</version>
  208.13 +    <version>0.9-SNAPSHOT</version>
  208.14    </parent>
  208.15    <groupId>org.apidesign.bck2brwsr</groupId>
  208.16    <artifactId>emul.mini</artifactId>
  208.17 -  <version>0.3-SNAPSHOT</version>
  208.18 +  <version>0.9-SNAPSHOT</version>
  208.19    <name>Minimal API Profile</name>
  208.20    <url>http://maven.apache.org</url>
  208.21    <properties>
  208.22 @@ -19,7 +18,7 @@
  208.23      <dependency>
  208.24        <groupId>org.apidesign.bck2brwsr</groupId>
  208.25        <artifactId>core</artifactId>
  208.26 -      <version>0.3-SNAPSHOT</version>
  208.27 +      <version>0.9-SNAPSHOT</version>
  208.28        <type>jar</type>
  208.29      </dependency>
  208.30      <dependency>
  208.31 @@ -43,6 +42,28 @@
  208.32                   <target>1.7</target>
  208.33                </configuration>
  208.34            </plugin>
  208.35 +          <plugin>
  208.36 +              <groupId>org.apache.maven.plugins</groupId>
  208.37 +              <artifactId>maven-javadoc-plugin</artifactId>
  208.38 +              <configuration>
  208.39 +                  <excludePackageNames>org.apidesign.bck2brwsr.emul.*</excludePackageNames>
  208.40 +                  <skip>false</skip>
  208.41 +              </configuration>
  208.42 +          </plugin>
  208.43 +          <plugin>
  208.44 +              <groupId>org.apache.maven.plugins</groupId>
  208.45 +              <artifactId>maven-source-plugin</artifactId>
  208.46 +              <version>2.2.1</version>
  208.47 +              <executions>
  208.48 +                  <execution>
  208.49 +                      <id>prepare-sources</id>
  208.50 +                      <goals>
  208.51 +                          <goal>jar</goal>
  208.52 +                      </goals>
  208.53 +                      <phase>package</phase>
  208.54 +                  </execution>
  208.55 +              </executions>
  208.56 +          </plugin>
  208.57        </plugins>
  208.58    </build>
  208.59  </project>
   209.1 --- a/rt/emul/mini/src/main/java/java/lang/AbstractStringBuilder.java	Wed Feb 27 17:50:47 2013 +0100
   209.2 +++ b/rt/emul/mini/src/main/java/java/lang/AbstractStringBuilder.java	Mon Oct 07 14:20:58 2013 +0200
   209.3 @@ -126,7 +126,7 @@
   209.4                  throw new OutOfMemoryError();
   209.5              newCapacity = Integer.MAX_VALUE;
   209.6          }
   209.7 -        value = copyOf(value, newCapacity);
   209.8 +        value = System.expandArray(value, newCapacity);
   209.9      }
  209.10  
  209.11      /**
   210.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   210.2 +++ b/rt/emul/mini/src/main/java/java/lang/ArithmeticException.java	Mon Oct 07 14:20:58 2013 +0200
   210.3 @@ -0,0 +1,61 @@
   210.4 +/*
   210.5 + * Copyright (c) 1994, 2011, Oracle and/or its affiliates. All rights reserved.
   210.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   210.7 + *
   210.8 + * This code is free software; you can redistribute it and/or modify it
   210.9 + * under the terms of the GNU General Public License version 2 only, as
  210.10 + * published by the Free Software Foundation.  Oracle designates this
  210.11 + * particular file as subject to the "Classpath" exception as provided
  210.12 + * by Oracle in the LICENSE file that accompanied this code.
  210.13 + *
  210.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  210.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  210.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  210.17 + * version 2 for more details (a copy is included in the LICENSE file that
  210.18 + * accompanied this code).
  210.19 + *
  210.20 + * You should have received a copy of the GNU General Public License version
  210.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  210.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  210.23 + *
  210.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  210.25 + * or visit www.oracle.com if you need additional information or have any
  210.26 + * questions.
  210.27 + */
  210.28 +
  210.29 +package java.lang;
  210.30 +
  210.31 +/**
  210.32 + * Thrown when an exceptional arithmetic condition has occurred. For
  210.33 + * example, an integer "divide by zero" throws an
  210.34 + * instance of this class.
  210.35 + *
  210.36 + * {@code ArithmeticException} objects may be constructed by the
  210.37 + * virtual machine as if {@linkplain Throwable#Throwable(String,
  210.38 + * Throwable, boolean, boolean) suppression were disabled and/or the
  210.39 + * stack trace was not writable}.
  210.40 + *
  210.41 + * @author  unascribed
  210.42 + * @since   JDK1.0
  210.43 + */
  210.44 +public class ArithmeticException extends RuntimeException {
  210.45 +    private static final long serialVersionUID = 2256477558314496007L;
  210.46 +
  210.47 +    /**
  210.48 +     * Constructs an {@code ArithmeticException} with no detail
  210.49 +     * message.
  210.50 +     */
  210.51 +    public ArithmeticException() {
  210.52 +        super();
  210.53 +    }
  210.54 +
  210.55 +    /**
  210.56 +     * Constructs an {@code ArithmeticException} with the specified
  210.57 +     * detail message.
  210.58 +     *
  210.59 +     * @param   s   the detail message.
  210.60 +     */
  210.61 +    public ArithmeticException(String s) {
  210.62 +        super(s);
  210.63 +    }
  210.64 +}
   211.1 --- a/rt/emul/mini/src/main/java/java/lang/Boolean.java	Wed Feb 27 17:50:47 2013 +0100
   211.2 +++ b/rt/emul/mini/src/main/java/java/lang/Boolean.java	Mon Oct 07 14:20:58 2013 +0200
   211.3 @@ -25,6 +25,9 @@
   211.4  
   211.5  package java.lang;
   211.6  
   211.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   211.8 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
   211.9 +
  211.10  /**
  211.11   * The Boolean class wraps a value of the primitive type
  211.12   * {@code boolean} in an object. An object of type
  211.13 @@ -40,6 +43,7 @@
  211.14   * @author  Arthur van Hoff
  211.15   * @since   JDK1.0
  211.16   */
  211.17 +@JavaScriptPrototype(container = "Boolean.prototype", prototype = "new Boolean")
  211.18  public final class Boolean implements java.io.Serializable,
  211.19                                        Comparable<Boolean>
  211.20  {
  211.21 @@ -127,6 +131,7 @@
  211.22       *
  211.23       * @return  the primitive {@code boolean} value of this object.
  211.24       */
  211.25 +    @JavaScriptBody(args = {}, body = "return this.valueOf();")
  211.26      public boolean booleanValue() {
  211.27          return value;
  211.28      }
  211.29 @@ -279,4 +284,13 @@
  211.30      private static boolean toBoolean(String name) {
  211.31          return ((name != null) && name.equalsIgnoreCase("true"));
  211.32      }
  211.33 +    static {
  211.34 +        // as last step of initialization, initialize valueOf method
  211.35 +        initValueOf();
  211.36 +    }
  211.37 +    @JavaScriptBody(args = {  }, body = 
  211.38 +        "vm.java_lang_Boolean(false)" +
  211.39 +        ".valueOf = function() { return this._value() ? true : false; };"
  211.40 +    )
  211.41 +    private native static void initValueOf();
  211.42  }
   212.1 --- a/rt/emul/mini/src/main/java/java/lang/Character.java	Wed Feb 27 17:50:47 2013 +0100
   212.2 +++ b/rt/emul/mini/src/main/java/java/lang/Character.java	Mon Oct 07 14:20:58 2013 +0200
   212.3 @@ -2298,6 +2298,10 @@
   212.4       */
   212.5      @Deprecated
   212.6      public static boolean isSpace(char ch) {
   212.7 +        return isSpaceChar(ch);
   212.8 +    }
   212.9 +
  212.10 +    public static boolean isSpaceChar(int ch) {
  212.11          return (ch <= 0x0020) &&
  212.12              (((((1L << 0x0009) |
  212.13              (1L << 0x000A) |
  212.14 @@ -2307,7 +2311,6 @@
  212.15      }
  212.16  
  212.17  
  212.18 -
  212.19      /**
  212.20       * Determines if the specified character is white space according to Java.
  212.21       * A character is a Java whitespace character if and only if it satisfies
  212.22 @@ -2372,7 +2375,14 @@
  212.23       * @since   1.5
  212.24       */
  212.25      public static boolean isWhitespace(int codePoint) {
  212.26 -        throw new UnsupportedOperationException();
  212.27 +        if (
  212.28 +            codePoint == SPACE_SEPARATOR || 
  212.29 +            codePoint == LINE_SEPARATOR || 
  212.30 +            codePoint == PARAGRAPH_SEPARATOR
  212.31 +        ) {
  212.32 +            return true;
  212.33 +        }
  212.34 +        return false;
  212.35      }
  212.36  
  212.37      /**
  212.38 @@ -2516,4 +2526,14 @@
  212.39          return (char) (((ch & 0xFF00) >> 8) | (ch << 8));
  212.40      }
  212.41  
  212.42 +    static {
  212.43 +        // as last step of initialization, initialize valueOf method
  212.44 +        initValueOf();
  212.45 +    }
  212.46 +    @JavaScriptBody(args = {}, body = 
  212.47 +        "vm.java_lang_Character(false)." +
  212.48 +        "valueOf = function() { return this._value(); };"
  212.49 +    )
  212.50 +    private native static void initValueOf();
  212.51 +    
  212.52  }
   213.1 --- a/rt/emul/mini/src/main/java/java/lang/Class.java	Wed Feb 27 17:50:47 2013 +0100
   213.2 +++ b/rt/emul/mini/src/main/java/java/lang/Class.java	Mon Oct 07 14:20:58 2013 +0200
   213.3 @@ -155,11 +155,15 @@
   213.4              }
   213.5              return arrType;
   213.6          }
   213.7 -        Class<?> c = loadCls(className, className.replace('.', '_'));
   213.8 -        if (c == null) {
   213.9 -            throw new ClassNotFoundException(className);
  213.10 +        try {
  213.11 +            Class<?> c = loadCls(className, className.replace('.', '_'));
  213.12 +            if (c == null) {
  213.13 +                throw new ClassNotFoundException(className);
  213.14 +            }
  213.15 +            return c;
  213.16 +        } catch (Throwable ex) {
  213.17 +            throw new ClassNotFoundException(className, ex);
  213.18          }
  213.19 -        return c;
  213.20      }
  213.21  
  213.22  
  213.23 @@ -402,8 +406,15 @@
  213.24              }
  213.25              return cmpType != null && getComponentType().isAssignableFrom(cmpType);
  213.26          }
  213.27 -        String prop = "$instOf_" + getName().replace('.', '_');
  213.28 -        return hasCnstrProperty(cls, prop);
  213.29 +        if (isPrimitive()) {
  213.30 +            return false;
  213.31 +        } else {
  213.32 +            if (cls.isPrimitive()) {
  213.33 +                return false;
  213.34 +            }
  213.35 +            String prop = "$instOf_" + getName().replace('.', '_');
  213.36 +            return hasCnstrProperty(cls, prop);
  213.37 +        }
  213.38      }
  213.39  
  213.40      @JavaScriptBody(args = { "who", "prop" }, body = 
  213.41 @@ -1245,6 +1256,7 @@
  213.42      }
  213.43      
  213.44      @JavaScriptBody(args = { "sig" }, body = 
  213.45 +        "if (!sig) sig = '[Ljava/lang/Object;';\n" +
  213.46          "var c = Array[sig];\n" +
  213.47          "if (c) return c;\n" +
  213.48          "c = vm.java_lang_Class(true);\n" +
   214.1 --- a/rt/emul/mini/src/main/java/java/lang/Double.java	Wed Feb 27 17:50:47 2013 +0100
   214.2 +++ b/rt/emul/mini/src/main/java/java/lang/Double.java	Mon Oct 07 14:20:58 2013 +0200
   214.3 @@ -190,12 +190,12 @@
   214.4       * @param   d   the {@code double} to be converted.
   214.5       * @return a string representation of the argument.
   214.6       */
   214.7 -    @JavaScriptBody(args="d", body="var r = d.toString();"
   214.8 -        + "if (isFinite(d) && (r.indexOf('.') === -1)) r = r + '.0';"
   214.9 -        + "return r;")
  214.10 -    public static String toString(double d) {
  214.11 -        throw new UnsupportedOperationException();
  214.12 -    }
  214.13 +    @JavaScriptBody(args="d", body="var f = Math.floor(d);\n" +
  214.14 +        "var r = d.toString();" +
  214.15 +        "if (f === d && isFinite(d) && r.indexOf('e') === -1) return r + '.0';\n" +
  214.16 +        " else return r;"
  214.17 +    )
  214.18 +    public static native String toString(double d);
  214.19  
  214.20      /**
  214.21       * Returns a hexadecimal string representation of the
  214.22 @@ -502,10 +502,8 @@
  214.23       * @throws     NumberFormatException  if the string does not contain a
  214.24       *             parsable number.
  214.25       */
  214.26 -    @JavaScriptBody(args="s", body="return parseFloat(s);")
  214.27      public static Double valueOf(String s) throws NumberFormatException {
  214.28 -        throw new UnsupportedOperationException();
  214.29 -//        return new Double(FloatingDecimal.readJavaFormatString(s).doubleValue());
  214.30 +        return new Double(parseDouble(s));
  214.31      }
  214.32  
  214.33      /**
  214.34 @@ -810,15 +808,17 @@
  214.35       * @return the bits that represent the floating-point number.
  214.36       */
  214.37      public static long doubleToLongBits(double value) {
  214.38 -        throw new UnsupportedOperationException();
  214.39 -//        long result = doubleToRawLongBits(value);
  214.40 -//        // Check for NaN based on values of bit fields, maximum
  214.41 -//        // exponent and nonzero significand.
  214.42 -//        if ( ((result & DoubleConsts.EXP_BIT_MASK) ==
  214.43 -//              DoubleConsts.EXP_BIT_MASK) &&
  214.44 -//             (result & DoubleConsts.SIGNIF_BIT_MASK) != 0L)
  214.45 -//            result = 0x7ff8000000000000L;
  214.46 -//        return result;
  214.47 +        final long EXP_BIT_MASK = 9218868437227405312L;
  214.48 +        final long SIGNIF_BIT_MASK = 4503599627370495L;
  214.49 +        
  214.50 +        long result = doubleToRawLongBits(value);
  214.51 +        // Check for NaN based on values of bit fields, maximum
  214.52 +        // exponent and nonzero significand.
  214.53 +        if ( ((result & EXP_BIT_MASK) ==
  214.54 +              EXP_BIT_MASK) &&
  214.55 +             (result & SIGNIF_BIT_MASK) != 0L)
  214.56 +            result = 0x7ff8000000000000L;
  214.57 +        return result;
  214.58      }
  214.59  
  214.60      /**
  214.61 @@ -857,7 +857,21 @@
  214.62       * @return the bits that represent the floating-point number.
  214.63       * @since 1.3
  214.64       */
  214.65 -    public static native long doubleToRawLongBits(double value);
  214.66 +    public static long doubleToRawLongBits(double value) {
  214.67 +        int[] arr = { 0, 0 };
  214.68 +        doubleToRawLongBits(value, arr);
  214.69 +        long l = arr[1];
  214.70 +        return (l << 32) | arr[0];
  214.71 +    }
  214.72 +    
  214.73 +    @JavaScriptBody(args = { "value", "arr" }, body = ""
  214.74 +        + "var a = new ArrayBuffer(8);"
  214.75 +        + "new Float64Array(a)[0] = value;"
  214.76 +        + "var out = new Int32Array(a);"
  214.77 +        + "arr[0] = out[0];"
  214.78 +        + "arr[1] = out[1];"
  214.79 +    )
  214.80 +    private static native void doubleToRawLongBits(double value, int[] arr);
  214.81  
  214.82      /**
  214.83       * Returns the {@code double} value corresponding to a given
   215.1 --- a/rt/emul/mini/src/main/java/java/lang/Enum.java	Wed Feb 27 17:50:47 2013 +0100
   215.2 +++ b/rt/emul/mini/src/main/java/java/lang/Enum.java	Mon Oct 07 14:20:58 2013 +0200
   215.3 @@ -27,6 +27,7 @@
   215.4  
   215.5  import java.io.Serializable;
   215.6  import java.io.IOException;
   215.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   215.8  
   215.9  /**
  215.10   * This is the common base class of all Java language enumeration types.
  215.11 @@ -225,15 +226,17 @@
  215.12       */
  215.13      public static <T extends Enum<T>> T valueOf(Class<T> enumType,
  215.14                                                  String name) {
  215.15 -        throw new UnsupportedOperationException();
  215.16 -//        T result = enumType.enumConstantDirectory().get(name);
  215.17 -//        if (result != null)
  215.18 -//            return result;
  215.19 -//        if (name == null)
  215.20 -//            throw new NullPointerException("Name is null");
  215.21 -//        throw new IllegalArgumentException(
  215.22 -//            "No enum constant " + enumType.getCanonicalName() + "." + name);
  215.23 +        for (Object o : values(enumType)) {
  215.24 +            T t = enumType.cast(o);
  215.25 +            if (name.equals(((Enum)t).name)) {
  215.26 +                return t;
  215.27 +            }
  215.28 +        }
  215.29 +        throw new IllegalArgumentException();
  215.30      }
  215.31 +    
  215.32 +    @JavaScriptBody(args = { "enumType" }, body = "return enumType.cnstr.$VALUES;")
  215.33 +    private static native Object[] values(Class<?> enumType);
  215.34  
  215.35      /**
  215.36       * enum classes cannot have finalize methods.
   216.1 --- a/rt/emul/mini/src/main/java/java/lang/Float.java	Wed Feb 27 17:50:47 2013 +0100
   216.2 +++ b/rt/emul/mini/src/main/java/java/lang/Float.java	Mon Oct 07 14:20:58 2013 +0200
   216.3 @@ -710,15 +710,17 @@
   216.4       * @return the bits that represent the floating-point number.
   216.5       */
   216.6      public static int floatToIntBits(float value) {
   216.7 -        throw new UnsupportedOperationException();
   216.8 -//        int result = floatToRawIntBits(value);
   216.9 -//        // Check for NaN based on values of bit fields, maximum
  216.10 -//        // exponent and nonzero significand.
  216.11 -//        if ( ((result & FloatConsts.EXP_BIT_MASK) ==
  216.12 -//              FloatConsts.EXP_BIT_MASK) &&
  216.13 -//             (result & FloatConsts.SIGNIF_BIT_MASK) != 0)
  216.14 -//            result = 0x7fc00000;
  216.15 -//        return result;
  216.16 +        final int EXP_BIT_MASK = 2139095040;
  216.17 +        final int SIGNIF_BIT_MASK = 8388607;
  216.18 +        
  216.19 +        int result = floatToRawIntBits(value);
  216.20 +        // Check for NaN based on values of bit fields, maximum
  216.21 +        // exponent and nonzero significand.
  216.22 +        if ( ((result & EXP_BIT_MASK) ==
  216.23 +              EXP_BIT_MASK) &&
  216.24 +             (result & SIGNIF_BIT_MASK) != 0)
  216.25 +            result = 0x7fc00000;
  216.26 +        return result;
  216.27      }
  216.28  
  216.29      /**
  216.30 @@ -756,6 +758,11 @@
  216.31       * @return the bits that represent the floating-point number.
  216.32       * @since 1.3
  216.33       */
  216.34 +    @JavaScriptBody(args = { "value" }, body = ""
  216.35 +        + "var a = new ArrayBuffer(4);"
  216.36 +        + "new Float32Array(a)[0] = value;"
  216.37 +        + "return new Int32Array(a)[0];"
  216.38 +    )
  216.39      public static native int floatToRawIntBits(float value);
  216.40  
  216.41      /**
   217.1 --- a/rt/emul/mini/src/main/java/java/lang/Number.java	Wed Feb 27 17:50:47 2013 +0100
   217.2 +++ b/rt/emul/mini/src/main/java/java/lang/Number.java	Mon Oct 07 14:20:58 2013 +0200
   217.3 @@ -27,7 +27,6 @@
   217.4  
   217.5  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
   217.6  import org.apidesign.bck2brwsr.core.JavaScriptBody;
   217.7 -import org.apidesign.bck2brwsr.core.JavaScriptOnly;
   217.8  import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
   217.9  
  217.10  /**
   218.1 --- a/rt/emul/mini/src/main/java/java/lang/Object.java	Wed Feb 27 17:50:47 2013 +0100
   218.2 +++ b/rt/emul/mini/src/main/java/java/lang/Object.java	Mon Oct 07 14:20:58 2013 +0200
   218.3 @@ -42,14 +42,21 @@
   218.4  public class Object {
   218.5  
   218.6      private static void registerNatives() {
   218.7 -        try {
   218.8 +        boolean assertsOn = false;
   218.9 +        assert assertsOn = false;
  218.10 +        if (assertsOn) try {
  218.11              Array.get(null, 0);
  218.12          } catch (Throwable ex) {
  218.13              // ignore
  218.14          }
  218.15      }
  218.16 +    @JavaScriptBody(args = {}, body = "var p = vm.java_lang_Object(false);" +
  218.17 +        "p.toString = function() { return this.toString__Ljava_lang_String_2(); };"
  218.18 +    )
  218.19 +    private static native void registerToString();
  218.20      static {
  218.21          registerNatives();
  218.22 +        registerToString();
  218.23      }
  218.24  
  218.25      /**
  218.26 @@ -72,9 +79,17 @@
  218.27       * @see    Class Literals, section 15.8.2 of
  218.28       *         <cite>The Java&trade; Language Specification</cite>.
  218.29       */
  218.30 -    @JavaScriptBody(args={}, body="return this.constructor.$class;")
  218.31 -    public final native Class<?> getClass();
  218.32 +    public final Class<?> getClass() {
  218.33 +        Class<?> c = getClassImpl();
  218.34 +        return c == null ? Object.class : c;
  218.35 +    }
  218.36  
  218.37 +    @JavaScriptBody(args={}, body=
  218.38 +          "var c = this.constructor.$class;\n"
  218.39 +        + "return c ? c : null;\n"
  218.40 +    )
  218.41 +    private final native Class<?> getClassImpl();
  218.42 +    
  218.43      /**
  218.44       * Returns a hash code value for the object. This method is
  218.45       * supported for the benefit of hash tables such as those provided by
  218.46 @@ -110,12 +125,15 @@
  218.47       * @see     java.lang.Object#equals(java.lang.Object)
  218.48       * @see     java.lang.System#identityHashCode
  218.49       */
  218.50 +    public int hashCode() {
  218.51 +        return defaultHashCode();
  218.52 +    }
  218.53      @JavaScriptBody(args = {}, body = 
  218.54          "if (this.$hashCode) return this.$hashCode;\n"
  218.55          + "var h = this.computeHashCode__I();\n"
  218.56          + "return this.$hashCode = h & h;"
  218.57      )
  218.58 -    public native int hashCode();
  218.59 +    final native int defaultHashCode();
  218.60  
  218.61      @JavaScriptBody(args = {}, body = "return Math.random() * Math.pow(2, 32);")
  218.62      native int computeHashCode();
  218.63 @@ -310,7 +328,8 @@
  218.64       * @see        java.lang.Object#notifyAll()
  218.65       * @see        java.lang.Object#wait()
  218.66       */
  218.67 -    public final native void notify();
  218.68 +    public final void notify() {
  218.69 +    }
  218.70  
  218.71      /**
  218.72       * Wakes up all threads that are waiting on this object's monitor. A
  218.73 @@ -334,7 +353,8 @@
  218.74       * @see        java.lang.Object#notify()
  218.75       * @see        java.lang.Object#wait()
  218.76       */
  218.77 -    public final native void notifyAll();
  218.78 +    public final void notifyAll() {
  218.79 +    }
  218.80  
  218.81      /**
  218.82       * Causes the current thread to wait until either another thread invokes the
  218.83 @@ -421,7 +441,9 @@
  218.84       * @see        java.lang.Object#notify()
  218.85       * @see        java.lang.Object#notifyAll()
  218.86       */
  218.87 -    public final native void wait(long timeout) throws InterruptedException;
  218.88 +    public final void wait(long timeout) throws InterruptedException {
  218.89 +        throw new InterruptedException();
  218.90 +    }
  218.91  
  218.92      /**
  218.93       * Causes the current thread to wait until another thread invokes the
  218.94 @@ -486,20 +508,7 @@
  218.95       *             this exception is thrown.
  218.96       */
  218.97      public final void wait(long timeout, int nanos) throws InterruptedException {
  218.98 -        if (timeout < 0) {
  218.99 -            throw new IllegalArgumentException("timeout value is negative");
 218.100 -        }
 218.101 -
 218.102 -        if (nanos < 0 || nanos > 999999) {
 218.103 -            throw new IllegalArgumentException(
 218.104 -                                "nanosecond timeout value out of range");
 218.105 -        }
 218.106 -
 218.107 -        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {
 218.108 -            timeout++;
 218.109 -        }
 218.110 -
 218.111 -        wait(timeout);
 218.112 +        throw new InterruptedException();
 218.113      }
 218.114  
 218.115      /**
 218.116 @@ -541,7 +550,7 @@
 218.117       * @see        java.lang.Object#notifyAll()
 218.118       */
 218.119      public final void wait() throws InterruptedException {
 218.120 -        wait(0);
 218.121 +        throw new InterruptedException();
 218.122      }
 218.123  
 218.124      /**
   219.1 --- a/rt/emul/mini/src/main/java/java/lang/String.java	Wed Feb 27 17:50:47 2013 +0100
   219.2 +++ b/rt/emul/mini/src/main/java/java/lang/String.java	Mon Oct 07 14:20:58 2013 +0200
   219.3 @@ -115,15 +115,17 @@
   219.4  
   219.5      /** use serialVersionUID from JDK 1.0.2 for interoperability */
   219.6      private static final long serialVersionUID = -6849794470754667710L;
   219.7 +
   219.8 +    static {
   219.9 +        registerToString();
  219.10 +    }
  219.11 +    @JavaScriptBody(args = {}, body = 
  219.12 +          "var p = vm.java_lang_String(false);\n"
  219.13 +        + "p.toString = function() {\nreturn this._r().toString();\n};\n"
  219.14 +        + "p.valueOf = function() {\nreturn this._r().valueOf();\n}\n"
  219.15 +    )
  219.16 +    private static native void registerToString();
  219.17      
  219.18 -    @JavaScriptOnly(name="toString", value="String.prototype._r")
  219.19 -    private static void jsToString() {
  219.20 -    }
  219.21 -    
  219.22 -    @JavaScriptOnly(name="valueOf", value="function() { return this.toString().valueOf(); }")
  219.23 -    private static void jsValudOf() {
  219.24 -    }
  219.25 -
  219.26      /**
  219.27       * Class String is special cased within the Serialization Stream Protocol.
  219.28       *
  219.29 @@ -2218,9 +2220,19 @@
  219.30       *         <code>replacement</code> is <code>null</code>.
  219.31       * @since 1.5
  219.32       */
  219.33 -    public String replace(CharSequence target, CharSequence replacement) {
  219.34 -        throw new UnsupportedOperationException("This one should be supported, but without dep on rest of regexp");
  219.35 -    }
  219.36 +    @JavaScriptBody(args = { "target", "replacement" }, body = 
  219.37 +          "var s = this.toString();\n"
  219.38 +        + "target = target.toString();\n"
  219.39 +        + "replacement = replacement.toString();\n"
  219.40 +        + "for (;;) {\n"
  219.41 +        + "  var ret = s.replace(target, replacement);\n"
  219.42 +        + "  if (ret === s) {\n"
  219.43 +        + "    return ret;\n"
  219.44 +        + "  }\n"
  219.45 +        + "  s = ret;\n"
  219.46 +        + "}"
  219.47 +    )
  219.48 +    public native String replace(CharSequence target, CharSequence replacement);
  219.49  
  219.50      /**
  219.51       * Splits this string around matches of the given
  219.52 @@ -2303,8 +2315,35 @@
  219.53       * @spec JSR-51
  219.54       */
  219.55      public String[] split(String regex, int limit) {
  219.56 -        throw new UnsupportedOperationException("Needs regexp");
  219.57 +        if (limit <= 0) {
  219.58 +            Object[] arr = splitImpl(this, regex, Integer.MAX_VALUE);
  219.59 +            int to = arr.length;
  219.60 +            if (limit == 0) {
  219.61 +                while (to > 1 && ((String)arr[--to]).isEmpty()) {
  219.62 +                }
  219.63 +                to++;
  219.64 +            }
  219.65 +            String[] ret = new String[to];
  219.66 +            System.arraycopy(arr, 0, ret, 0, to);
  219.67 +            return ret;
  219.68 +        } else {
  219.69 +            Object[] arr = splitImpl(this, regex, limit);
  219.70 +            String[] ret = new String[arr.length];
  219.71 +            int pos = 0;
  219.72 +            for (int i = 0; i < arr.length; i++) {
  219.73 +                final String s = (String)arr[i];
  219.74 +                ret[i] = s;
  219.75 +                pos = indexOf(s, pos) + s.length();
  219.76 +            }
  219.77 +            ret[arr.length - 1] += substring(pos);
  219.78 +            return ret;
  219.79 +        }
  219.80      }
  219.81 +    
  219.82 +    @JavaScriptBody(args = { "str", "regex", "limit"}, body = 
  219.83 +        "return str.split(new RegExp(regex), limit);"
  219.84 +    )
  219.85 +    private static native Object[] splitImpl(String str, String regex, int limit);
  219.86  
  219.87      /**
  219.88       * Splits this string around matches of the given <a
   220.1 --- a/rt/emul/mini/src/main/java/java/lang/Throwable.java	Wed Feb 27 17:50:47 2013 +0100
   220.2 +++ b/rt/emul/mini/src/main/java/java/lang/Throwable.java	Mon Oct 07 14:20:58 2013 +0200
   220.3 @@ -638,10 +638,9 @@
   220.4       *          ... 2 more
   220.5       * </pre>
   220.6       */
   220.7 -//    public void printStackTrace() {
   220.8 -//        printStackTrace(System.err);
   220.9 -//    }
  220.10 -//
  220.11 +    @JavaScriptBody(args = {  }, body = "console.warn(this.toString());")
  220.12 +    public native void printStackTrace();
  220.13 +
  220.14  //    /**
  220.15  //     * Prints this throwable and its backtrace to the specified print stream.
  220.16  //     *
  220.17 @@ -1085,4 +1084,22 @@
  220.18  //        else
  220.19  //            return suppressedExceptions.toArray(EMPTY_THROWABLE_ARRAY);
  220.20      }
  220.21 +    
  220.22 +    private static Object bck2BrwsrCnvrt(Object o) {
  220.23 +        if (o instanceof Throwable) {
  220.24 +            return o;
  220.25 +        }
  220.26 +        final String msg = msg(o);
  220.27 +        if (msg == null || msg.startsWith("TypeError")) {
  220.28 +            return new NullPointerException(msg);
  220.29 +        }
  220.30 +        return new Throwable(msg);
  220.31 +    }
  220.32 +    
  220.33 +    @JavaScriptBody(args = { "o" }, body = "return o ? o.toString() : null;")
  220.34 +    private static native String msg(Object o);
  220.35 +
  220.36 +    @JavaScriptOnly(name = "bck2BrwsrCnvrt", value = "c.bck2BrwsrCnvrt__Ljava_lang_Object_2Ljava_lang_Object_2")
  220.37 +    private static void bck2BrwsrCnvrtVM() {
  220.38 +    }
  220.39  }
   221.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Array.java	Wed Feb 27 17:50:47 2013 +0100
   221.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Array.java	Mon Oct 07 14:20:58 2013 +0200
   221.3 @@ -636,9 +636,9 @@
   221.4          + "arr.jvmName = sig;\n"
   221.5          + "return arr;"
   221.6      )
   221.7 -    private static native Object newArray(boolean primitive, String sig, int length);
   221.8 +    static native Object newArray(boolean primitive, String sig, int length);
   221.9  
  221.10 -    private static Object multiNewArray(String sig, int[] dims, int index)
  221.11 +    static Object multiNewArray(String sig, int[] dims, int index)
  221.12      throws IllegalArgumentException, NegativeArraySizeException {
  221.13          if (dims.length == index + 1) {
  221.14              return newArray(sig.length() == 2, sig, dims[index]);
   222.1 --- a/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Wed Feb 27 17:50:47 2013 +0100
   222.2 +++ b/rt/emul/mini/src/main/java/java/lang/reflect/Method.java	Mon Oct 07 14:20:58 2013 +0200
   222.3 @@ -501,8 +501,8 @@
   222.4          throws IllegalAccessException, IllegalArgumentException,
   222.5             InvocationTargetException
   222.6      {
   222.7 -        final boolean isStatic = (getModifiers() & Modifier.STATIC) == 0;
   222.8 -        if (isStatic && obj == null) {
   222.9 +        final boolean nonStatic = (getModifiers() & Modifier.STATIC) == 0;
  222.10 +        if (nonStatic && obj == null) {
  222.11              throw new NullPointerException();
  222.12          }
  222.13          Class[] types = getParameterTypes();
  222.14 @@ -512,12 +512,12 @@
  222.15              args = args.clone();
  222.16              for (int i = 0; i < types.length; i++) {
  222.17                  Class c = types[i];
  222.18 -                if (c.isPrimitive()) {
  222.19 -                    args[i] = toPrimitive(c, args[i]);
  222.20 +                if (c.isPrimitive() && args[i] != null) {
  222.21 +                    args[i] = toPrimitive(args[i]);
  222.22                  }
  222.23              }
  222.24          }
  222.25 -        Object res = invoke0(isStatic, this, obj, args);
  222.26 +        Object res = invokeTry(nonStatic, this, obj, args);
  222.27          if (getReturnType().isPrimitive()) {
  222.28              res = fromPrimitive(getReturnType(), res);
  222.29          }
  222.30 @@ -536,6 +536,15 @@
  222.31          + "return method._data().apply(self, p);\n"
  222.32      )
  222.33      private static native Object invoke0(boolean isStatic, Method m, Object self, Object[] args);
  222.34 +    
  222.35 +    private static Object invokeTry(boolean isStatic, Method m, Object self, Object[] args)
  222.36 +    throws InvocationTargetException {
  222.37 +        try {
  222.38 +            return invoke0(isStatic, m, self, args);
  222.39 +        } catch (Throwable ex) {
  222.40 +            throw new InvocationTargetException(ex, ex.getMessage());
  222.41 +        }
  222.42 +    }
  222.43  
  222.44      static Object fromPrimitive(Class<?> type, Object o) {
  222.45          if (type == Integer.TYPE) {
  222.46 @@ -573,41 +582,8 @@
  222.47      )
  222.48      private static native Integer fromRaw(Class<?> cls, String m, Object o);
  222.49  
  222.50 -    private static Object toPrimitive(Class<?> type, Object o) {
  222.51 -        if (type == Integer.TYPE) {
  222.52 -            return toRaw("intValue__I", o);
  222.53 -        }
  222.54 -        if (type == Long.TYPE) {
  222.55 -            return toRaw("longValue__J", o);
  222.56 -        }
  222.57 -        if (type == Double.TYPE) {
  222.58 -            return toRaw("doubleValue__D", o);
  222.59 -        }
  222.60 -        if (type == Float.TYPE) {
  222.61 -            return toRaw("floatValue__F", o);
  222.62 -        }
  222.63 -        if (type == Byte.TYPE) {
  222.64 -            return toRaw("byteValue__B", o);
  222.65 -        }
  222.66 -        if (type == Boolean.TYPE) {
  222.67 -            return toRaw("booleanValue__Z", o);
  222.68 -        }
  222.69 -        if (type == Short.TYPE) {
  222.70 -            return toRaw("shortValue__S", o);
  222.71 -        }
  222.72 -        if (type == Character.TYPE) {
  222.73 -            return toRaw("charValue__C", o);
  222.74 -        }
  222.75 -        if (type.getName().equals("void")) {
  222.76 -            return o;
  222.77 -        }
  222.78 -        throw new IllegalStateException("Can't convert " + o);
  222.79 -    }
  222.80 -    
  222.81 -    @JavaScriptBody(args = { "m", "o" }, 
  222.82 -        body = "return o[m](o);"
  222.83 -    )
  222.84 -    private static native Object toRaw(String m, Object o);
  222.85 +    @JavaScriptBody(args = { "o" }, body = "return o.valueOf();")
  222.86 +    private static native Object toPrimitive(Object o);
  222.87      
  222.88      /**
  222.89       * Returns {@code true} if this method is a bridge
   223.1 --- a/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Wed Feb 27 17:50:47 2013 +0100
   223.2 +++ b/rt/emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/lang/System.java	Mon Oct 07 14:20:58 2013 +0200
   223.3 @@ -54,6 +54,11 @@
   223.4      )
   223.5      public static native byte[] expandArray(byte[] arr, int expectedSize);
   223.6  
   223.7 +    @JavaScriptBody(args = { "arr", "expectedSize" }, body = 
   223.8 +        "while (expectedSize-- > arr.length) { arr.push(0); }; return arr;"
   223.9 +    )
  223.10 +    public static native char[] expandArray(char[] arr, int expectedSize);
  223.11 +
  223.12      @JavaScriptBody(args = {}, body = "return new Date().getTime();")
  223.13      private static native double currentTimeMillisDouble();
  223.14  
   224.1 --- a/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Wed Feb 27 17:50:47 2013 +0100
   224.2 +++ b/rt/emul/mini/src/main/resources/org/apidesign/vm4brwsr/emul/lang/java_lang_Number.js	Mon Oct 07 14:20:58 2013 +0200
   224.3 @@ -1,226 +1,244 @@
   224.4  // empty line needed here
   224.5 -Number.prototype.add32 = function(x) { return (this + x) | 0; };
   224.6 -Number.prototype.sub32 = function(x) { return (this - x) | 0; };
   224.7 -Number.prototype.mul32 = function(x) { 
   224.8 -    return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
   224.9 -};
  224.10 -Number.prototype.neg32 = function() { return (-this) | 0; };
  224.11  
  224.12 -Number.prototype.toInt8 = function()  { return (this << 24) >> 24; };
  224.13 -Number.prototype.toInt16 = function() { return (this << 16) >> 16; };
  224.14 +(function(numberPrototype) {
  224.15 +    numberPrototype.add32 = function(x) {
  224.16 +        return (this + x) | 0;
  224.17 +    };
  224.18 +    numberPrototype.sub32 = function(x) {
  224.19 +        return (this - x) | 0;
  224.20 +    };
  224.21 +    numberPrototype.mul32 = function(x) {
  224.22 +        return (((this * (x >> 16)) << 16) + this * (x & 0xFFFF)) | 0;
  224.23 +    };
  224.24 +    numberPrototype.neg32 = function() {
  224.25 +        return (-this) | 0;
  224.26 +    };
  224.27  
  224.28 -var __m32 = 0xFFFFFFFF;
  224.29 +    numberPrototype.toInt8 = function() {
  224.30 +        return (this << 24) >> 24;
  224.31 +    };
  224.32 +    numberPrototype.toInt16 = function() {
  224.33 +        return (this << 16) >> 16;
  224.34 +    };
  224.35  
  224.36 -Number.prototype.next32 = function(low) {
  224.37 -  if (this === 0) {
  224.38 -    return low;
  224.39 -  }
  224.40 -  var l = new Number(low);
  224.41 -  l.hi = this | 0;
  224.42 -  return l;
  224.43 -};
  224.44 +    var __m32 = 0xFFFFFFFF;
  224.45  
  224.46 -Number.prototype.high32 = function() { 
  224.47 -    return this.hi ? this.hi : (Math.floor(this / (__m32+1))) | 0;
  224.48 -};
  224.49 -Number.prototype.toInt32 = function() { return this | 0; };
  224.50 -Number.prototype.toFP = function() {
  224.51 -    return this.hi ? this.hi * (__m32+1) + this : this;
  224.52 -};
  224.53 -Number.prototype.toLong = function() {
  224.54 -    var hi = (this / (__m32+1)) | 0;
  224.55 -    var low = (this % (__m32+1)) | 0;
  224.56 -    if (low < 0) {
  224.57 -        low += __m32+1;
  224.58 -    }
  224.59 -        
  224.60 -    if (this < 0) {
  224.61 -        hi -= 1;
  224.62 -    }
  224.63 +    numberPrototype.next32 = function(low) {
  224.64 +        if (this === 0) {
  224.65 +            return low;
  224.66 +        }
  224.67 +        var l = new Number(low);
  224.68 +        l.hi = this | 0;
  224.69 +        return l;
  224.70 +    };
  224.71  
  224.72 -    return hi.next32(low);
  224.73 -};
  224.74 +    numberPrototype.high32 = function() {
  224.75 +        return this.hi ? this.hi : (Math.floor(this / (__m32 + 1))) | 0;
  224.76 +    };
  224.77 +    numberPrototype.toInt32 = function() {
  224.78 +        return this | 0;
  224.79 +    };
  224.80 +    numberPrototype.toFP = function() {
  224.81 +        return this.hi ? this.hi * (__m32 + 1) + this : this;
  224.82 +    };
  224.83 +    numberPrototype.toLong = function() {
  224.84 +        var hi = (this / (__m32 + 1)) | 0;
  224.85 +        var low = (this % (__m32 + 1)) | 0;
  224.86 +        if (low < 0) {
  224.87 +            low += __m32 + 1;
  224.88 +        }
  224.89  
  224.90 -Number.prototype.toExactString = function() {
  224.91 -    if (this.hi) {
  224.92 -        // check for Long.MIN_VALUE
  224.93 -        if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
  224.94 -            return '-9223372036854775808';
  224.95 +        if (this < 0) {
  224.96 +            hi -= 1;
  224.97          }
  224.98 -        var res = 0;
  224.99 -        var a = [ 6,9,2,7,6,9,4,9,2,4 ];
 224.100 -        var s = '';
 224.101 -        var digit;
 224.102 -        var neg = this.hi < 0;
 224.103 -        if (neg) {
 224.104 -            var x = this.neg64();
 224.105 -            var hi = x.hi;
 224.106 -            var low = x;
 224.107 -        } else {
 224.108 -            var hi = this.hi;
 224.109 -            var low = this;
 224.110 -        }
 224.111 -        for (var i = 0; i < a.length; i++) {
 224.112 -            res += hi * a[i];
 224.113 -            var low_digit = low % 10;
 224.114 -            digit = (res % 10) + low_digit;
 224.115  
 224.116 -            low = Math.floor(low / 10);
 224.117 -            res = Math.floor(res / 10);
 224.118 -
 224.119 -            if (digit >= 10) {
 224.120 -                digit -= 10;
 224.121 -                res++;
 224.122 -            }
 224.123 -            s = String(digit).concat(s);
 224.124 -        }
 224.125 -        s = String(res).concat(s).replace(/^0+/, '');
 224.126 -        return (neg ? '-' : '').concat(s);
 224.127 -    }
 224.128 -    return String(this);
 224.129 -};
 224.130 -
 224.131 -Number.prototype.add64 = function(x) {
 224.132 -    var low = this + x;
 224.133 -    carry = 0;
 224.134 -    if (low > __m32) {
 224.135 -        carry = 1;
 224.136 -        low -= (__m32+1);
 224.137 -    }
 224.138 -    var hi = (this.high32() + x.high32() + carry) | 0;
 224.139 -    return hi.next32(low);
 224.140 -};
 224.141 -
 224.142 -Number.prototype.sub64 = function(x) {
 224.143 -    var low = this - x;
 224.144 -    carry = 0;
 224.145 -    if (low < 0) {
 224.146 -        carry = 1;
 224.147 -        low += (__m32+1);
 224.148 -    }
 224.149 -    var hi = (this.high32() - x.high32() - carry) | 0;
 224.150 -    return hi.next32(low);
 224.151 -};
 224.152 -
 224.153 -Number.prototype.mul64 = function(x) {
 224.154 -    var low = this.mul32(x);
 224.155 -    low += (low < 0) ? (__m32+1) : 0;
 224.156 -    // first count upper 32 bits of (this.low * x.low)
 224.157 -    var hi_hi = 0;
 224.158 -    var hi_low = 0;
 224.159 -    var m = 1;
 224.160 -    for (var i = 0; i < 32; i++) {
 224.161 -        if (x & m) {
 224.162 -            hi_hi += this >>> 16;
 224.163 -            hi_low += this & 0xFFFF
 224.164 -        }
 224.165 -        hi_low >>= 1;
 224.166 -        hi_low += (hi_hi & 1) ? 0x8000 : 0;
 224.167 -        hi_hi >>= 1;
 224.168 -        m <<= 1;
 224.169 -    }
 224.170 -    var hi = (hi_hi << 16) + hi_low;
 224.171 -    
 224.172 -    var m1 = this.high32().mul32(x);
 224.173 -    var m2 = this.mul32(x.high32());
 224.174 -    hi = hi.add32(m1).add32(m2);
 224.175 -    
 224.176 -    return hi.next32(low);
 224.177 -};
 224.178 -
 224.179 -Number.prototype.and64 = function(x) {
 224.180 -    var low = this & x;
 224.181 -    low += (low < 0) ? (__m32+1) : 0;
 224.182 -    if (this.hi && x.hi) {
 224.183 -        var hi = this.hi & x.hi;
 224.184          return hi.next32(low);
 224.185      };
 224.186 -    return low;
 224.187 -};
 224.188  
 224.189 -Number.prototype.or64 = function(x) {
 224.190 -    var low = this | x;
 224.191 -    low += (low < 0) ? (__m32+1) : 0;
 224.192 -    if (this.hi || x.hi) {
 224.193 -        var hi = this.hi | x.hi;
 224.194 +    numberPrototype.toExactString = function() {
 224.195 +        if (this.hi) {
 224.196 +            // check for Long.MIN_VALUE
 224.197 +            if ((this.hi == (0x80000000 | 0)) && (this == 0)) {
 224.198 +                return '-9223372036854775808';
 224.199 +            }
 224.200 +            var res = 0;
 224.201 +            var a = [6, 9, 2, 7, 6, 9, 4, 9, 2, 4];
 224.202 +            var s = '';
 224.203 +            var digit;
 224.204 +            var neg = this.hi < 0;
 224.205 +            if (neg) {
 224.206 +                var x = this.neg64();
 224.207 +                var hi = x.hi;
 224.208 +                var low = x;
 224.209 +            } else {
 224.210 +                var hi = this.hi;
 224.211 +                var low = this;
 224.212 +            }
 224.213 +            for (var i = 0; i < a.length; i++) {
 224.214 +                res += hi * a[i];
 224.215 +                var low_digit = low % 10;
 224.216 +                digit = (res % 10) + low_digit;
 224.217 +
 224.218 +                low = Math.floor(low / 10);
 224.219 +                res = Math.floor(res / 10);
 224.220 +
 224.221 +                if (digit >= 10) {
 224.222 +                    digit -= 10;
 224.223 +                    res++;
 224.224 +                }
 224.225 +                s = String(digit).concat(s);
 224.226 +            }
 224.227 +            s = String(res).concat(s).replace(/^0+/, '');
 224.228 +            return (neg ? '-' : '').concat(s);
 224.229 +        }
 224.230 +        return String(this);
 224.231 +    };
 224.232 +
 224.233 +    numberPrototype.add64 = function(x) {
 224.234 +        var low = this + x;
 224.235 +        carry = 0;
 224.236 +        if (low > __m32) {
 224.237 +            carry = 1;
 224.238 +            low -= (__m32 + 1);
 224.239 +        }
 224.240 +        var hi = (this.high32() + x.high32() + carry) | 0;
 224.241          return hi.next32(low);
 224.242      };
 224.243 -    return low;
 224.244 -};
 224.245  
 224.246 -Number.prototype.xor64 = function(x) {
 224.247 -    var low = this ^ x;
 224.248 -    low += (low < 0) ? (__m32+1) : 0;
 224.249 -    if (this.hi || x.hi) {
 224.250 -        var hi = this.hi ^ x.hi;
 224.251 +    numberPrototype.sub64 = function(x) {
 224.252 +        var low = this - x;
 224.253 +        carry = 0;
 224.254 +        if (low < 0) {
 224.255 +            carry = 1;
 224.256 +            low += (__m32 + 1);
 224.257 +        }
 224.258 +        var hi = (this.high32() - x.high32() - carry) | 0;
 224.259          return hi.next32(low);
 224.260      };
 224.261 -    return low;
 224.262 -};
 224.263  
 224.264 -Number.prototype.shl64 = function(x) {
 224.265 -    if (x >= 32) {
 224.266 -        var hi = this << (x - 32);
 224.267 -        return hi.next32(0);
 224.268 -    } else {
 224.269 -        var hi = this.high32() << x;
 224.270 -        var low_reminder = this >> (32 - x);
 224.271 -        hi |= low_reminder;
 224.272 -        var low = this << x;
 224.273 -        low += (low < 0) ? (__m32+1) : 0;
 224.274 +    numberPrototype.mul64 = function(x) {
 224.275 +        var low = this.mul32(x);
 224.276 +        low += (low < 0) ? (__m32 + 1) : 0;
 224.277 +        // first count upper 32 bits of (this.low * x.low)
 224.278 +        var hi_hi = 0;
 224.279 +        var hi_low = 0;
 224.280 +        var m = 1;
 224.281 +        for (var i = 0; i < 32; i++) {
 224.282 +            if (x & m) {
 224.283 +                hi_hi += this >>> 16;
 224.284 +                hi_low += this & 0xFFFF
 224.285 +            }
 224.286 +            hi_low >>= 1;
 224.287 +            hi_low += (hi_hi & 1) ? 0x8000 : 0;
 224.288 +            hi_hi >>= 1;
 224.289 +            m <<= 1;
 224.290 +        }
 224.291 +        var hi = (hi_hi << 16) + hi_low;
 224.292 +
 224.293 +        var m1 = this.high32().mul32(x);
 224.294 +        var m2 = this.mul32(x.high32());
 224.295 +        hi = hi.add32(m1).add32(m2);
 224.296 +
 224.297          return hi.next32(low);
 224.298 -    }
 224.299 -};
 224.300 +    };
 224.301  
 224.302 -Number.prototype.shr64 = function(x) {
 224.303 -    if (x >= 32) {
 224.304 -        var low = this.high32() >> (x - 32);
 224.305 -        low += (low < 0) ? (__m32+1) : 0;
 224.306 +    numberPrototype.and64 = function(x) {
 224.307 +        var low = this & x;
 224.308 +        low += (low < 0) ? (__m32 + 1) : 0;
 224.309 +        if (this.hi && x.hi) {
 224.310 +            var hi = this.hi & x.hi;
 224.311 +            return hi.next32(low);
 224.312 +        }
 224.313 +        ;
 224.314          return low;
 224.315 -    } else {
 224.316 -        var low = this >> x;
 224.317 -        var hi_reminder = this.high32() << (32 - x);
 224.318 -        low |= hi_reminder;
 224.319 -        low += (low < 0) ? (__m32+1) : 0;
 224.320 -        var hi = this.high32() >> x;
 224.321 -        return hi.next32(low);
 224.322 -    }
 224.323 -};
 224.324 +    };
 224.325  
 224.326 -Number.prototype.ushr64 = function(x) {
 224.327 -    if (x >= 32) {
 224.328 -        var low = this.high32() >>> (x - 32);
 224.329 -        low += (low < 0) ? (__m32+1) : 0;
 224.330 +    numberPrototype.or64 = function(x) {
 224.331 +        var low = this | x;
 224.332 +        low += (low < 0) ? (__m32 + 1) : 0;
 224.333 +        if (this.hi || x.hi) {
 224.334 +            var hi = this.hi | x.hi;
 224.335 +            return hi.next32(low);
 224.336 +        }
 224.337 +        ;
 224.338          return low;
 224.339 -    } else {
 224.340 -        var low = this >>> x;
 224.341 -        var hi_reminder = this.high32() << (32 - x);
 224.342 -        low |= hi_reminder;
 224.343 -        low += (low < 0) ? (__m32+1) : 0;
 224.344 -        var hi = this.high32() >>> x;
 224.345 -        return hi.next32(low);
 224.346 -    }
 224.347 -};
 224.348 +    };
 224.349  
 224.350 -Number.prototype.compare64 = function(x) {
 224.351 -    if (this.high32() === x.high32()) {
 224.352 -        return (this < x) ? -1 : ((this > x) ? 1 : 0);
 224.353 -    }
 224.354 -    return (this.high32() < x.high32()) ? -1 : 1;
 224.355 -};
 224.356 +    numberPrototype.xor64 = function(x) {
 224.357 +        var low = this ^ x;
 224.358 +        low += (low < 0) ? (__m32 + 1) : 0;
 224.359 +        if (this.hi || x.hi) {
 224.360 +            var hi = this.hi ^ x.hi;
 224.361 +            return hi.next32(low);
 224.362 +        }
 224.363 +        ;
 224.364 +        return low;
 224.365 +    };
 224.366  
 224.367 -Number.prototype.neg64 = function() {
 224.368 -    var hi = this.high32();
 224.369 -    var low = this;
 224.370 -    if ((hi === 0) && (low < 0)) { return -low; }
 224.371 -    hi = ~hi;
 224.372 -    low = ~low;
 224.373 -    low += (low < 0) ? (__m32+1) : 0;
 224.374 -    var ret = hi.next32(low);
 224.375 -    return ret.add64(1);
 224.376 -};
 224.377 +    numberPrototype.shl64 = function(x) {
 224.378 +        if (x >= 32) {
 224.379 +            var hi = this << (x - 32);
 224.380 +            return hi.next32(0);
 224.381 +        } else {
 224.382 +            var hi = this.high32() << x;
 224.383 +            var low_reminder = this >> (32 - x);
 224.384 +            hi |= low_reminder;
 224.385 +            var low = this << x;
 224.386 +            low += (low < 0) ? (__m32 + 1) : 0;
 224.387 +            return hi.next32(low);
 224.388 +        }
 224.389 +    };
 224.390  
 224.391 -(function(numberPrototype) {
 224.392 +    numberPrototype.shr64 = function(x) {
 224.393 +        if (x >= 32) {
 224.394 +            var low = this.high32() >> (x - 32);
 224.395 +            low += (low < 0) ? (__m32 + 1) : 0;
 224.396 +            return low;
 224.397 +        } else {
 224.398 +            var low = this >> x;
 224.399 +            var hi_reminder = this.high32() << (32 - x);
 224.400 +            low |= hi_reminder;
 224.401 +            low += (low < 0) ? (__m32 + 1) : 0;
 224.402 +            var hi = this.high32() >> x;
 224.403 +            return hi.next32(low);
 224.404 +        }
 224.405 +    };
 224.406 +
 224.407 +    numberPrototype.ushr64 = function(x) {
 224.408 +        if (x >= 32) {
 224.409 +            var low = this.high32() >>> (x - 32);
 224.410 +            low += (low < 0) ? (__m32 + 1) : 0;
 224.411 +            return low;
 224.412 +        } else {
 224.413 +            var low = this >>> x;
 224.414 +            var hi_reminder = this.high32() << (32 - x);
 224.415 +            low |= hi_reminder;
 224.416 +            low += (low < 0) ? (__m32 + 1) : 0;
 224.417 +            var hi = this.high32() >>> x;
 224.418 +            return hi.next32(low);
 224.419 +        }
 224.420 +    };
 224.421 +
 224.422 +    numberPrototype.compare64 = function(x) {
 224.423 +        if (this.high32() === x.high32()) {
 224.424 +            return (this < x) ? -1 : ((this > x) ? 1 : 0);
 224.425 +        }
 224.426 +        return (this.high32() < x.high32()) ? -1 : 1;
 224.427 +    };
 224.428 +
 224.429 +    numberPrototype.neg64 = function() {
 224.430 +        var hi = this.high32();
 224.431 +        var low = this;
 224.432 +        if ((hi === 0) && (low < 0)) {
 224.433 +            return -low;
 224.434 +        }
 224.435 +        hi = ~hi;
 224.436 +        low = ~low;
 224.437 +        low += (low < 0) ? (__m32 + 1) : 0;
 224.438 +        var ret = hi.next32(low);
 224.439 +        return ret.add64(1);
 224.440 +    };
 224.441 +    
 224.442      function __handleDivByZero() {
 224.443          var exception = new vm.java_lang_ArithmeticException;
 224.444          vm.java_lang_ArithmeticException(false).constructor
 224.445 @@ -551,3 +569,5 @@
 224.446          return negateResult ? result.neg64() : result; 
 224.447      }
 224.448  })(Number.prototype);
 224.449 +
 224.450 +vm.java_lang_Number(false);
   225.1 --- a/rt/emul/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   225.2 +++ b/rt/emul/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   225.3 @@ -4,15 +4,16 @@
   225.4    <parent>
   225.5      <groupId>org.apidesign.bck2brwsr</groupId>
   225.6      <artifactId>rt</artifactId>
   225.7 -    <version>0.3-SNAPSHOT</version>
   225.8 +    <version>0.9-SNAPSHOT</version>
   225.9    </parent>
  225.10    <groupId>org.apidesign.bck2brwsr</groupId>
  225.11    <artifactId>emul.pom</artifactId>
  225.12 -  <version>0.3-SNAPSHOT</version>
  225.13 +  <version>0.9-SNAPSHOT</version>
  225.14    <packaging>pom</packaging>
  225.15    <name>Emulation of Core Libraries</name>
  225.16    <modules>
  225.17      <module>mini</module>
  225.18      <module>compact</module>
  225.19 +    <module>brwsrtest</module>
  225.20    </modules>
  225.21  </project>
   226.1 --- a/rt/javap/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   226.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   226.3 @@ -1,41 +0,0 @@
   226.4 -<?xml version="1.0"?>
   226.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   226.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   226.7 -  <modelVersion>4.0.0</modelVersion>
   226.8 -  <parent>
   226.9 -    <groupId>org.apidesign.bck2brwsr</groupId>
  226.10 -    <artifactId>rt</artifactId>
  226.11 -    <version>0.3-SNAPSHOT</version>
  226.12 -  </parent>
  226.13 -  <groupId>org.apidesign.bck2brwsr</groupId>
  226.14 -  <artifactId>javap</artifactId>
  226.15 -  <version>0.3-SNAPSHOT</version>
  226.16 -  <name>ByteCode Parser</name>
  226.17 -  <url>http://maven.apache.org</url>
  226.18 -  <properties>
  226.19 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  226.20 -  </properties>
  226.21 -  <build>
  226.22 -      <plugins>
  226.23 -          <plugin>
  226.24 -              <groupId>org.apache.maven.plugins</groupId>
  226.25 -              <artifactId>maven-compiler-plugin</artifactId>
  226.26 -              <version>2.5.1</version>
  226.27 -              <configuration>
  226.28 -                  <compilerArguments>
  226.29 -                      <!--<bootclasspath>non-existing</bootclasspath>-->
  226.30 -                  </compilerArguments>
  226.31 -                 <source>1.6</source>
  226.32 -                 <target>1.6</target>
  226.33 -              </configuration>
  226.34 -          </plugin>
  226.35 -      </plugins>
  226.36 -  </build>
  226.37 -  <dependencies>
  226.38 -    <dependency>
  226.39 -      <groupId>org.apidesign.bck2brwsr</groupId>
  226.40 -      <artifactId>emul.mini</artifactId>
  226.41 -      <version>0.3-SNAPSHOT</version>
  226.42 -    </dependency>
  226.43 -  </dependencies>
  226.44 -</project>
   227.1 --- a/rt/javap/src/main/java/org/apidesign/javap/AnnotationParser.java	Wed Feb 27 17:50:47 2013 +0100
   227.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   227.3 @@ -1,145 +0,0 @@
   227.4 -/*
   227.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   227.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   227.7 - *
   227.8 - * This code is free software; you can redistribute it and/or modify it
   227.9 - * under the terms of the GNU General Public License version 2 only, as
  227.10 - * published by the Free Software Foundation.  Oracle designates this
  227.11 - * particular file as subject to the "Classpath" exception as provided
  227.12 - * by Oracle in the LICENSE file that accompanied this code.
  227.13 - *
  227.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  227.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  227.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  227.17 - * version 2 for more details (a copy is included in the LICENSE file that
  227.18 - * accompanied this code).
  227.19 - *
  227.20 - * You should have received a copy of the GNU General Public License version
  227.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  227.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  227.23 - *
  227.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  227.25 - * or visit www.oracle.com if you need additional information or have any
  227.26 - * questions.
  227.27 - */
  227.28 -package org.apidesign.javap;
  227.29 -
  227.30 -import java.io.ByteArrayInputStream;
  227.31 -import java.io.DataInputStream;
  227.32 -import java.io.IOException;
  227.33 -
  227.34 -/** An abstract parser for annotation definitions. Analyses the bytes and
  227.35 - * performs some callbacks to the overriden parser methods.
  227.36 - *
  227.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  227.38 - */
  227.39 -public class AnnotationParser {
  227.40 -    private final boolean textual;
  227.41 -    private final boolean iterateArray;
  227.42 -    
  227.43 -    protected AnnotationParser(boolean textual, boolean iterateArray) {
  227.44 -        this.textual = textual;
  227.45 -        this.iterateArray = iterateArray;
  227.46 -    }
  227.47 -
  227.48 -    protected void visitAnnotationStart(String type, boolean top) throws IOException {
  227.49 -    }
  227.50 -
  227.51 -    protected void visitAnnotationEnd(String type, boolean top) throws IOException {
  227.52 -    }
  227.53 -
  227.54 -    protected void visitValueStart(String attrName, char type) throws IOException {
  227.55 -    }
  227.56 -
  227.57 -    protected void visitValueEnd(String attrName, char type) throws IOException {
  227.58 -    }
  227.59 -
  227.60 -    
  227.61 -    protected void visitAttr(
  227.62 -        String annoType, String attr, String attrType, String value
  227.63 -    ) throws IOException {
  227.64 -    }
  227.65 -    
  227.66 -    protected void visitEnumAttr(
  227.67 -        String annoType, String attr, String attrType, String value
  227.68 -    ) throws IOException {
  227.69 -        visitAttr(annoType, attr, attrType, value);
  227.70 -    }
  227.71 -    
  227.72 -    /** Initialize the parsing with constant pool from <code>cd</code>.
  227.73 -     * 
  227.74 -     * @param attr the attribute defining annotations
  227.75 -     * @param cd constant pool
  227.76 -     * @throws IOException in case I/O fails
  227.77 -     */
  227.78 -    public final void parse(byte[] attr, ClassData cd) throws IOException {
  227.79 -        ByteArrayInputStream is = new ByteArrayInputStream(attr);
  227.80 -        DataInputStream dis = new DataInputStream(is);
  227.81 -        try {
  227.82 -            read(dis, cd);
  227.83 -        } finally {
  227.84 -            is.close();
  227.85 -        }
  227.86 -    }
  227.87 -    
  227.88 -    private void read(DataInputStream dis, ClassData cd) throws IOException {
  227.89 -    	int cnt = dis.readUnsignedShort();
  227.90 -        for (int i = 0; i < cnt; i++) {
  227.91 -            readAnno(dis, cd, true);
  227.92 -        }
  227.93 -    }
  227.94 -
  227.95 -    private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
  227.96 -        int type = dis.readUnsignedShort();
  227.97 -        String typeName = cd.StringValue(type);
  227.98 -        visitAnnotationStart(typeName, top);
  227.99 -    	int cnt = dis.readUnsignedShort();
 227.100 -    	for (int i = 0; i < cnt; i++) {
 227.101 -            String attrName = cd.StringValue(dis.readUnsignedShort());
 227.102 -            readValue(dis, cd, typeName, attrName);
 227.103 -        }
 227.104 -        visitAnnotationEnd(typeName, top);
 227.105 -        if (cnt == 0) {
 227.106 -            visitAttr(typeName, null, null, null);
 227.107 -        }
 227.108 -    }
 227.109 -
 227.110 -    private void readValue(
 227.111 -        DataInputStream dis, ClassData cd, String typeName, String attrName
 227.112 -    ) throws IOException {
 227.113 -        char type = (char)dis.readByte();
 227.114 -        visitValueStart(attrName, type);
 227.115 -        if (type == '@') {
 227.116 -            readAnno(dis, cd, false);
 227.117 -        } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
 227.118 -            int primitive = dis.readUnsignedShort();
 227.119 -            String val = cd.stringValue(primitive, textual);
 227.120 -            String attrType;
 227.121 -            if (type == 's') {
 227.122 -                attrType = "Ljava_lang_String_2";
 227.123 -                if (textual) {
 227.124 -                    val = '"' + val + '"';
 227.125 -                }
 227.126 -            } else {
 227.127 -                attrType = "" + type;
 227.128 -            }
 227.129 -            visitAttr(typeName, attrName, attrType, val);
 227.130 -        } else if (type == 'c') {
 227.131 -            int cls = dis.readUnsignedShort();
 227.132 -        } else if (type == '[') {
 227.133 -            int cnt = dis.readUnsignedShort();
 227.134 -            for (int i = 0; i < cnt; i++) {
 227.135 -                readValue(dis, cd, typeName, iterateArray ? attrName : null);
 227.136 -            }
 227.137 -        } else if (type == 'e') {
 227.138 -            int enumT = dis.readUnsignedShort();
 227.139 -            String attrType = cd.stringValue(enumT, textual);
 227.140 -            int enumN = dis.readUnsignedShort();
 227.141 -            String val = cd.stringValue(enumN, textual);
 227.142 -            visitEnumAttr(typeName, attrName, attrType, val);
 227.143 -        } else {
 227.144 -            throw new IOException("Unknown type " + type);
 227.145 -        }
 227.146 -        visitValueEnd(attrName, type);
 227.147 -    }
 227.148 -}
   228.1 --- a/rt/javap/src/main/java/org/apidesign/javap/AttrData.java	Wed Feb 27 17:50:47 2013 +0100
   228.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   228.3 @@ -1,77 +0,0 @@
   228.4 -/*
   228.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   228.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   228.7 - *
   228.8 - * This code is free software; you can redistribute it and/or modify it
   228.9 - * under the terms of the GNU General Public License version 2 only, as
  228.10 - * published by the Free Software Foundation.  Oracle designates this
  228.11 - * particular file as subject to the "Classpath" exception as provided
  228.12 - * by Oracle in the LICENSE file that accompanied this code.
  228.13 - *
  228.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  228.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  228.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  228.17 - * version 2 for more details (a copy is included in the LICENSE file that
  228.18 - * accompanied this code).
  228.19 - *
  228.20 - * You should have received a copy of the GNU General Public License version
  228.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  228.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  228.23 - *
  228.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  228.25 - * or visit www.oracle.com if you need additional information or have any
  228.26 - * questions.
  228.27 - */
  228.28 -
  228.29 -
  228.30 -
  228.31 -package org.apidesign.javap;
  228.32 -
  228.33 -import java.io.*;
  228.34 -
  228.35 -/**
  228.36 - * Reads and stores attribute information.
  228.37 - *
  228.38 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  228.39 - */
  228.40 -class AttrData {
  228.41 -    ClassData cls;
  228.42 -    int name_cpx;
  228.43 -    int datalen;
  228.44 -    byte data[];
  228.45 -
  228.46 -    public AttrData (ClassData cls) {
  228.47 -        this.cls=cls;
  228.48 -    }
  228.49 -
  228.50 -    /**
  228.51 -     * Reads unknown attribute.
  228.52 -     */
  228.53 -    public void read(int name_cpx, DataInputStream in) throws IOException {
  228.54 -        this.name_cpx=name_cpx;
  228.55 -        datalen=in.readInt();
  228.56 -        data=new byte[datalen];
  228.57 -        in.readFully(data);
  228.58 -    }
  228.59 -
  228.60 -    /**
  228.61 -     * Reads just the name of known attribute.
  228.62 -     */
  228.63 -    public void read(int name_cpx){
  228.64 -        this.name_cpx=name_cpx;
  228.65 -    }
  228.66 -
  228.67 -    /**
  228.68 -     * Returns attribute name.
  228.69 -     */
  228.70 -    public String getAttrName(){
  228.71 -        return cls.getString(name_cpx);
  228.72 -    }
  228.73 -
  228.74 -    /**
  228.75 -     * Returns attribute data.
  228.76 -     */
  228.77 -    public byte[] getData(){
  228.78 -        return data;
  228.79 -    }
  228.80 -}
   229.1 --- a/rt/javap/src/main/java/org/apidesign/javap/CPX.java	Wed Feb 27 17:50:47 2013 +0100
   229.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   229.3 @@ -1,40 +0,0 @@
   229.4 -/*
   229.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   229.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   229.7 - *
   229.8 - * This code is free software; you can redistribute it and/or modify it
   229.9 - * under the terms of the GNU General Public License version 2 only, as
  229.10 - * published by the Free Software Foundation.  Oracle designates this
  229.11 - * particular file as subject to the "Classpath" exception as provided
  229.12 - * by Oracle in the LICENSE file that accompanied this code.
  229.13 - *
  229.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  229.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  229.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  229.17 - * version 2 for more details (a copy is included in the LICENSE file that
  229.18 - * accompanied this code).
  229.19 - *
  229.20 - * You should have received a copy of the GNU General Public License version
  229.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  229.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  229.23 - *
  229.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  229.25 - * or visit www.oracle.com if you need additional information or have any
  229.26 - * questions.
  229.27 - */
  229.28 -
  229.29 -
  229.30 -package org.apidesign.javap;
  229.31 -
  229.32 -/**
  229.33 - * Stores constant pool entry information with one field.
  229.34 - *
  229.35 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  229.36 - */
  229.37 -class CPX {
  229.38 -    int cpx;
  229.39 -
  229.40 -    CPX (int cpx) {
  229.41 -        this.cpx=cpx;
  229.42 -    }
  229.43 -}
   230.1 --- a/rt/javap/src/main/java/org/apidesign/javap/CPX2.java	Wed Feb 27 17:50:47 2013 +0100
   230.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   230.3 @@ -1,41 +0,0 @@
   230.4 -/*
   230.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   230.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   230.7 - *
   230.8 - * This code is free software; you can redistribute it and/or modify it
   230.9 - * under the terms of the GNU General Public License version 2 only, as
  230.10 - * published by the Free Software Foundation.  Oracle designates this
  230.11 - * particular file as subject to the "Classpath" exception as provided
  230.12 - * by Oracle in the LICENSE file that accompanied this code.
  230.13 - *
  230.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  230.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  230.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  230.17 - * version 2 for more details (a copy is included in the LICENSE file that
  230.18 - * accompanied this code).
  230.19 - *
  230.20 - * You should have received a copy of the GNU General Public License version
  230.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  230.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  230.23 - *
  230.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  230.25 - * or visit www.oracle.com if you need additional information or have any
  230.26 - * questions.
  230.27 - */
  230.28 -
  230.29 -
  230.30 -package org.apidesign.javap;
  230.31 -
  230.32 -/**
  230.33 - *  Stores constant pool entry information with two fields.
  230.34 - *
  230.35 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  230.36 - */
  230.37 -class CPX2 {
  230.38 -    int cpx1,cpx2;
  230.39 -
  230.40 -    CPX2 (int cpx1, int cpx2) {
  230.41 -        this.cpx1=cpx1;
  230.42 -        this.cpx2=cpx2;
  230.43 -    }
  230.44 -}
   231.1 --- a/rt/javap/src/main/java/org/apidesign/javap/ClassData.java	Wed Feb 27 17:50:47 2013 +0100
   231.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   231.3 @@ -1,713 +0,0 @@
   231.4 -/*
   231.5 - * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
   231.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   231.7 - *
   231.8 - * This code is free software; you can redistribute it and/or modify it
   231.9 - * under the terms of the GNU General Public License version 2 only, as
  231.10 - * published by the Free Software Foundation.  Oracle designates this
  231.11 - * particular file as subject to the "Classpath" exception as provided
  231.12 - * by Oracle in the LICENSE file that accompanied this code.
  231.13 - *
  231.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  231.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  231.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  231.17 - * version 2 for more details (a copy is included in the LICENSE file that
  231.18 - * accompanied this code).
  231.19 - *
  231.20 - * You should have received a copy of the GNU General Public License version
  231.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  231.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  231.23 - *
  231.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  231.25 - * or visit www.oracle.com if you need additional information or have any
  231.26 - * questions.
  231.27 - */
  231.28 -
  231.29 -
  231.30 -package org.apidesign.javap;
  231.31 -
  231.32 -import java.io.*;
  231.33 -
  231.34 -/**
  231.35 - * Central data repository of the Java Disassembler.
  231.36 - * Stores all the information in java class file.
  231.37 - *
  231.38 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  231.39 - */
  231.40 -public final class ClassData implements RuntimeConstants {
  231.41 -
  231.42 -    private int magic;
  231.43 -    private int minor_version;
  231.44 -    private int major_version;
  231.45 -    private int cpool_count;
  231.46 -    private Object cpool[];
  231.47 -    private int access;
  231.48 -    private int this_class = 0;;
  231.49 -    private int super_class;
  231.50 -    private int interfaces_count;
  231.51 -    private int[] interfaces = new int[0];;
  231.52 -    private int fields_count;
  231.53 -    private FieldData[] fields;
  231.54 -    private int methods_count;
  231.55 -    private MethodData[] methods;
  231.56 -    private InnerClassData[] innerClasses;
  231.57 -    private int attributes_count;
  231.58 -    private AttrData[] attrs;
  231.59 -    private String classname;
  231.60 -    private String superclassname;
  231.61 -    private int source_cpx=0;
  231.62 -    private byte tags[];
  231.63 -    private Hashtable indexHashAscii = new Hashtable();
  231.64 -    private String pkgPrefix="";
  231.65 -    private int pkgPrefixLen=0;
  231.66 -
  231.67 -    /**
  231.68 -     * Read classfile to disassemble.
  231.69 -     */
  231.70 -    public ClassData(InputStream infile) throws IOException {
  231.71 -        this.read(new DataInputStream(infile));
  231.72 -    }
  231.73 -
  231.74 -    /**
  231.75 -     * Reads and stores class file information.
  231.76 -     */
  231.77 -    public void read(DataInputStream in) throws IOException {
  231.78 -        // Read the header
  231.79 -        magic = in.readInt();
  231.80 -        if (magic != JAVA_MAGIC) {
  231.81 -            throw new ClassFormatError("wrong magic: " +
  231.82 -                                       toHex(magic) + ", expected " +
  231.83 -                                       toHex(JAVA_MAGIC));
  231.84 -        }
  231.85 -        minor_version = in.readShort();
  231.86 -        major_version = in.readShort();
  231.87 -        if (major_version != JAVA_VERSION) {
  231.88 -        }
  231.89 -
  231.90 -        // Read the constant pool
  231.91 -        readCP(in);
  231.92 -        access = in.readUnsignedShort();
  231.93 -        this_class = in.readUnsignedShort();
  231.94 -        super_class = in.readUnsignedShort();
  231.95 -
  231.96 -        //Read interfaces.
  231.97 -        interfaces_count = in.readUnsignedShort();
  231.98 -        if(interfaces_count > 0){
  231.99 -            interfaces = new int[interfaces_count];
 231.100 -        }
 231.101 -        for (int i = 0; i < interfaces_count; i++) {
 231.102 -            interfaces[i]=in.readShort();
 231.103 -        }
 231.104 -
 231.105 -        // Read the fields
 231.106 -        readFields(in);
 231.107 -
 231.108 -        // Read the methods
 231.109 -        readMethods(in);
 231.110 -
 231.111 -        // Read the attributes
 231.112 -        attributes_count = in.readUnsignedShort();
 231.113 -        attrs=new AttrData[attributes_count];
 231.114 -        for (int k = 0; k < attributes_count; k++) {
 231.115 -            int name_cpx=in.readUnsignedShort();
 231.116 -            if (getTag(name_cpx)==CONSTANT_UTF8
 231.117 -                && getString(name_cpx).equals("SourceFile")
 231.118 -                ){      if (in.readInt()!=2)
 231.119 -                    throw new ClassFormatError("invalid attr length");
 231.120 -                source_cpx=in.readUnsignedShort();
 231.121 -                AttrData attr=new AttrData(this);
 231.122 -                attr.read(name_cpx);
 231.123 -                attrs[k]=attr;
 231.124 -
 231.125 -            } else if (getTag(name_cpx)==CONSTANT_UTF8
 231.126 -                       && getString(name_cpx).equals("InnerClasses")
 231.127 -                       ){       int length=in.readInt();
 231.128 -                       int num=in.readUnsignedShort();
 231.129 -                       if (2+num*8 != length)
 231.130 -                           throw new ClassFormatError("invalid attr length");
 231.131 -                       innerClasses=new InnerClassData[num];
 231.132 -                       for (int j = 0; j < num; j++) {
 231.133 -                           InnerClassData innerClass=new InnerClassData(this);
 231.134 -                           innerClass.read(in);
 231.135 -                           innerClasses[j]=innerClass;
 231.136 -                       }
 231.137 -                       AttrData attr=new AttrData(this);
 231.138 -                       attr.read(name_cpx);
 231.139 -                       attrs[k]=attr;
 231.140 -            } else {
 231.141 -                AttrData attr=new AttrData(this);
 231.142 -                attr.read(name_cpx, in);
 231.143 -                attrs[k]=attr;
 231.144 -            }
 231.145 -        }
 231.146 -        in.close();
 231.147 -    } // end ClassData.read()
 231.148 -
 231.149 -    /**
 231.150 -     * Reads and stores constant pool info.
 231.151 -     */
 231.152 -    void readCP(DataInputStream in) throws IOException {
 231.153 -        cpool_count = in.readUnsignedShort();
 231.154 -        tags = new byte[cpool_count];
 231.155 -        cpool = new Object[cpool_count];
 231.156 -        for (int i = 1; i < cpool_count; i++) {
 231.157 -            byte tag = in.readByte();
 231.158 -
 231.159 -            switch(tags[i] = tag) {
 231.160 -            case CONSTANT_UTF8:
 231.161 -                String str=in.readUTF();
 231.162 -                indexHashAscii.put(cpool[i] = str, new Integer(i));
 231.163 -                break;
 231.164 -            case CONSTANT_INTEGER:
 231.165 -                cpool[i] = new Integer(in.readInt());
 231.166 -                break;
 231.167 -            case CONSTANT_FLOAT:
 231.168 -                cpool[i] = new Float(in.readFloat());
 231.169 -                break;
 231.170 -            case CONSTANT_LONG:
 231.171 -                cpool[i++] = new Long(in.readLong());
 231.172 -                break;
 231.173 -            case CONSTANT_DOUBLE:
 231.174 -                cpool[i++] = new Double(in.readDouble());
 231.175 -                break;
 231.176 -            case CONSTANT_CLASS:
 231.177 -            case CONSTANT_STRING:
 231.178 -                cpool[i] = new CPX(in.readUnsignedShort());
 231.179 -                break;
 231.180 -
 231.181 -            case CONSTANT_FIELD:
 231.182 -            case CONSTANT_METHOD:
 231.183 -            case CONSTANT_INTERFACEMETHOD:
 231.184 -            case CONSTANT_NAMEANDTYPE:
 231.185 -                cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
 231.186 -                break;
 231.187 -
 231.188 -            case 0:
 231.189 -            default:
 231.190 -                throw new ClassFormatError("invalid constant type: " + (int)tags[i]);
 231.191 -            }
 231.192 -        }
 231.193 -    }
 231.194 -
 231.195 -    /**
 231.196 -     * Reads and strores field info.
 231.197 -     */
 231.198 -    protected void readFields(DataInputStream in) throws IOException {
 231.199 -        int fields_count = in.readUnsignedShort();
 231.200 -        fields=new FieldData[fields_count];
 231.201 -        for (int k = 0; k < fields_count; k++) {
 231.202 -            FieldData field=new FieldData(this);
 231.203 -            field.read(in);
 231.204 -            fields[k]=field;
 231.205 -        }
 231.206 -    }
 231.207 -
 231.208 -    /**
 231.209 -     * Reads and strores Method info.
 231.210 -     */
 231.211 -    protected void readMethods(DataInputStream in) throws IOException {
 231.212 -        int methods_count = in.readUnsignedShort();
 231.213 -        methods=new MethodData[methods_count];
 231.214 -        for (int k = 0; k < methods_count ; k++) {
 231.215 -            MethodData method=new MethodData(this);
 231.216 -            method.read(in);
 231.217 -            methods[k]=method;
 231.218 -        }
 231.219 -    }
 231.220 -
 231.221 -    /**
 231.222 -     * get a string
 231.223 -     */
 231.224 -    public String getString(int n) {
 231.225 -        if (n == 0) {
 231.226 -            return null; 
 231.227 -        } else {
 231.228 -            return (String)cpool[n];
 231.229 -        }
 231.230 -    }
 231.231 -
 231.232 -    /**
 231.233 -     * get the type of constant given an index
 231.234 -     */
 231.235 -    public byte getTag(int n) {
 231.236 -        try{
 231.237 -            return tags[n];
 231.238 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.239 -            return (byte)100;
 231.240 -        }
 231.241 -    }
 231.242 -
 231.243 -    static final String hexString="0123456789ABCDEF";
 231.244 -
 231.245 -    public static char hexTable[]=hexString.toCharArray();
 231.246 -
 231.247 -    static String toHex(long val, int width) {
 231.248 -        StringBuffer s = new StringBuffer();
 231.249 -        for (int i=width-1; i>=0; i--)
 231.250 -            s.append(hexTable[((int)(val>>(4*i)))&0xF]);
 231.251 -        return "0x"+s.toString();
 231.252 -    }
 231.253 -
 231.254 -    static String toHex(long val) {
 231.255 -        int width;
 231.256 -        for (width=16; width>0; width--) {
 231.257 -            if ((val>>(width-1)*4)!=0) break;
 231.258 -        }
 231.259 -        return toHex(val, width);
 231.260 -    }
 231.261 -
 231.262 -    static String toHex(int val) {
 231.263 -        int width;
 231.264 -        for (width=8; width>0; width--) {
 231.265 -            if ((val>>(width-1)*4)!=0) break;
 231.266 -        }
 231.267 -        return toHex(val, width);
 231.268 -    }
 231.269 -
 231.270 -    /**
 231.271 -     * Returns the name of this class.
 231.272 -     */
 231.273 -    public String getClassName() {
 231.274 -        String res=null;
 231.275 -        if (this_class==0) {
 231.276 -            return res;
 231.277 -        }
 231.278 -        int tcpx;
 231.279 -        try {
 231.280 -            if (tags[this_class]!=CONSTANT_CLASS) {
 231.281 -                return res; //"<CP["+cpx+"] is not a Class> ";
 231.282 -            }
 231.283 -            tcpx=((CPX)cpool[this_class]).cpx;
 231.284 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.285 -            return res; // "#"+cpx+"// invalid constant pool index";
 231.286 -        } catch (Throwable e) {
 231.287 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.288 -        }
 231.289 -
 231.290 -        try {
 231.291 -            return (String)(cpool[tcpx]);
 231.292 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.293 -            return  res; // "class #"+scpx+"// invalid constant pool index";
 231.294 -        } catch (ClassCastException e) {
 231.295 -            return  res; // "class #"+scpx+"// invalid constant pool reference";
 231.296 -        } catch (Throwable e) {
 231.297 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.298 -        }
 231.299 -
 231.300 -    }
 231.301 -
 231.302 -    /**
 231.303 -     * Returns the name of class at perticular index.
 231.304 -     */
 231.305 -    public String getClassName(int cpx) {
 231.306 -        String res="#"+cpx;
 231.307 -        if (cpx==0) {
 231.308 -            return res;
 231.309 -        }
 231.310 -        int scpx;
 231.311 -        try {
 231.312 -            if (tags[cpx]!=CONSTANT_CLASS) {
 231.313 -                return res; //"<CP["+cpx+"] is not a Class> ";
 231.314 -            }
 231.315 -            scpx=((CPX)cpool[cpx]).cpx;
 231.316 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.317 -            return res; // "#"+cpx+"// invalid constant pool index";
 231.318 -        } catch (Throwable e) {
 231.319 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.320 -        }
 231.321 -        res="#"+scpx;
 231.322 -        try {
 231.323 -            return (String)(cpool[scpx]);
 231.324 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.325 -            return  res; // "class #"+scpx+"// invalid constant pool index";
 231.326 -        } catch (ClassCastException e) {
 231.327 -            return  res; // "class #"+scpx+"// invalid constant pool reference";
 231.328 -        } catch (Throwable e) {
 231.329 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.330 -        }
 231.331 -    }
 231.332 -    
 231.333 -    public int getAccessFlags() {
 231.334 -        return access;
 231.335 -    }
 231.336 -
 231.337 -    /**
 231.338 -     * Returns true if it is a class
 231.339 -     */
 231.340 -    public boolean isClass() {
 231.341 -        if((access & ACC_INTERFACE) == 0) return true;
 231.342 -        return false;
 231.343 -    }
 231.344 -
 231.345 -    /**
 231.346 -     * Returns true if it is a interface.
 231.347 -     */
 231.348 -    public boolean isInterface(){
 231.349 -        if((access & ACC_INTERFACE) != 0) return true;
 231.350 -        return false;
 231.351 -    }
 231.352 -
 231.353 -    /**
 231.354 -     * Returns true if this member is public, false otherwise.
 231.355 -     */
 231.356 -    public boolean isPublic(){
 231.357 -        return (access & ACC_PUBLIC) != 0;
 231.358 -    }
 231.359 -
 231.360 -    /**
 231.361 -     * Returns the access of this class or interface.
 231.362 -     */
 231.363 -    public String[] getAccess(){
 231.364 -        Vector v = new Vector();
 231.365 -        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
 231.366 -        if ((access & ACC_FINAL)    !=0) v.addElement("final");
 231.367 -        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
 231.368 -        String[] accflags = new String[v.size()];
 231.369 -        v.copyInto(accflags);
 231.370 -        return accflags;
 231.371 -    }
 231.372 -
 231.373 -    /**
 231.374 -     * Returns list of innerclasses.
 231.375 -     */
 231.376 -    public InnerClassData[] getInnerClasses(){
 231.377 -        return innerClasses;
 231.378 -    }
 231.379 -
 231.380 -    /**
 231.381 -     * Returns list of attributes.
 231.382 -     */
 231.383 -    final AttrData[] getAttributes(){
 231.384 -        return attrs;
 231.385 -    }
 231.386 -    
 231.387 -    public byte[] findAnnotationData(boolean classRetention) {
 231.388 -        String n = classRetention ?
 231.389 -            "RuntimeInvisibleAnnotations" : // NOI18N
 231.390 -            "RuntimeVisibleAnnotations"; // NOI18N
 231.391 -        return findAttr(n, attrs);
 231.392 -    }
 231.393 -
 231.394 -    /**
 231.395 -     * Returns true if superbit is set.
 231.396 -     */
 231.397 -    public boolean isSuperSet(){
 231.398 -        if ((access & ACC_SUPER)   !=0) return true;
 231.399 -        return false;
 231.400 -    }
 231.401 -
 231.402 -    /**
 231.403 -     * Returns super class name.
 231.404 -     */
 231.405 -    public String getSuperClassName(){
 231.406 -        String res=null;
 231.407 -        if (super_class==0) {
 231.408 -            return res;
 231.409 -        }
 231.410 -        int scpx;
 231.411 -        try {
 231.412 -            if (tags[super_class]!=CONSTANT_CLASS) {
 231.413 -                return res; //"<CP["+cpx+"] is not a Class> ";
 231.414 -            }
 231.415 -            scpx=((CPX)cpool[super_class]).cpx;
 231.416 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.417 -            return res; // "#"+cpx+"// invalid constant pool index";
 231.418 -        } catch (Throwable e) {
 231.419 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.420 -        }
 231.421 -
 231.422 -        try {
 231.423 -            return (String)(cpool[scpx]);
 231.424 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.425 -            return  res; // "class #"+scpx+"// invalid constant pool index";
 231.426 -        } catch (ClassCastException e) {
 231.427 -            return  res; // "class #"+scpx+"// invalid constant pool reference";
 231.428 -        } catch (Throwable e) {
 231.429 -            return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
 231.430 -        }
 231.431 -    }
 231.432 -
 231.433 -    /**
 231.434 -     * Returns list of super interfaces.
 231.435 -     */
 231.436 -    public String[] getSuperInterfaces(){
 231.437 -        String interfacenames[] = new String[interfaces.length];
 231.438 -        int interfacecpx = -1;
 231.439 -        for(int i = 0; i < interfaces.length; i++){
 231.440 -            interfacecpx=((CPX)cpool[interfaces[i]]).cpx;
 231.441 -            interfacenames[i] = (String)(cpool[interfacecpx]);
 231.442 -        }
 231.443 -        return interfacenames;
 231.444 -    }
 231.445 -
 231.446 -    /**
 231.447 -     * Returns string at prticular constant pool index.
 231.448 -     */
 231.449 -    public String getStringValue(int cpoolx) {
 231.450 -        try {
 231.451 -            return ((String)cpool[cpoolx]);
 231.452 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.453 -            return "//invalid constant pool index:"+cpoolx;
 231.454 -        } catch (ClassCastException e) {
 231.455 -            return "//invalid constant pool ref:"+cpoolx;
 231.456 -        }
 231.457 -    }
 231.458 -
 231.459 -    /**
 231.460 -     * Returns list of field info.
 231.461 -     */
 231.462 -    public  FieldData[] getFields(){
 231.463 -        return fields;
 231.464 -    }
 231.465 -
 231.466 -    /**
 231.467 -     * Returns list of method info.
 231.468 -     */
 231.469 -    public  MethodData[] getMethods(){
 231.470 -        return methods;
 231.471 -    }
 231.472 -
 231.473 -    /**
 231.474 -     * Returns constant pool entry at that index.
 231.475 -     */
 231.476 -    public CPX2 getCpoolEntry(int cpx){
 231.477 -        return ((CPX2)(cpool[cpx]));
 231.478 -    }
 231.479 -
 231.480 -    public Object getCpoolEntryobj(int cpx){
 231.481 -        return (cpool[cpx]);
 231.482 -    }
 231.483 -
 231.484 -    /**
 231.485 -     * Returns index of this class.
 231.486 -     */
 231.487 -    public int getthis_cpx(){
 231.488 -        return this_class;
 231.489 -    }
 231.490 -
 231.491 -    /**
 231.492 -     * Returns string at that index.
 231.493 -     */
 231.494 -    public String StringValue(int cpx) {
 231.495 -        return stringValue(cpx, false);
 231.496 -    }
 231.497 -    public String stringValue(int cpx, boolean textual) {
 231.498 -        return stringValue(cpx, textual, null);
 231.499 -    }
 231.500 -    public String stringValue(int cpx, String[] classRefs) {
 231.501 -        return stringValue(cpx, true, classRefs);
 231.502 -    }
 231.503 -    private String stringValue(int cpx, boolean textual, String[] refs) {
 231.504 -        if (cpx==0) return "#0";
 231.505 -        int tag;
 231.506 -        Object x;
 231.507 -        String suffix="";
 231.508 -        try {
 231.509 -            tag=tags[cpx];
 231.510 -            x=cpool[cpx];
 231.511 -        } catch (IndexOutOfBoundsException e) {
 231.512 -            return "<Incorrect CP index:"+cpx+">";
 231.513 -        }
 231.514 -
 231.515 -        if (x==null) return "<NULL>";
 231.516 -        switch (tag) {
 231.517 -        case CONSTANT_UTF8: {
 231.518 -            if (!textual) {
 231.519 -                return (String)x;
 231.520 -            }
 231.521 -            StringBuilder sb=new StringBuilder();
 231.522 -            String s=(String)x;
 231.523 -            for (int k=0; k<s.length(); k++) {
 231.524 -                char c=s.charAt(k);
 231.525 -                switch (c) {
 231.526 -                case '\\': sb.append('\\').append('\\'); break;
 231.527 -                case '\t': sb.append('\\').append('t'); break;
 231.528 -                case '\n': sb.append('\\').append('n'); break;
 231.529 -                case '\r': sb.append('\\').append('r'); break;
 231.530 -                case '\"': sb.append('\\').append('\"'); break;
 231.531 -                default: sb.append(c);
 231.532 -                }
 231.533 -            }
 231.534 -            return sb.toString();
 231.535 -        }
 231.536 -        case CONSTANT_DOUBLE: {
 231.537 -            Double d=(Double)x;
 231.538 -            String sd=d.toString();
 231.539 -            if (textual) {
 231.540 -                return sd;
 231.541 -            }
 231.542 -            return sd+"d";
 231.543 -        }
 231.544 -        case CONSTANT_FLOAT: {
 231.545 -            Float f=(Float)x;
 231.546 -            String sf=(f).toString();
 231.547 -            if (textual) {
 231.548 -                return sf;
 231.549 -            }
 231.550 -            return sf+"f";
 231.551 -        }
 231.552 -        case CONSTANT_LONG: {
 231.553 -            Long ln = (Long)x;
 231.554 -            if (textual) {
 231.555 -                return ln.toString();
 231.556 -            }
 231.557 -            return ln.toString()+'l';
 231.558 -        }
 231.559 -        case CONSTANT_INTEGER: {
 231.560 -            Integer in = (Integer)x;
 231.561 -            return in.toString();
 231.562 -        }
 231.563 -        case CONSTANT_CLASS:
 231.564 -            String jn = getClassName(cpx);
 231.565 -            if (textual) {
 231.566 -                if (refs != null) {
 231.567 -                    refs[0] = jn;
 231.568 -                }
 231.569 -                return jn;
 231.570 -            }
 231.571 -            return javaName(jn);
 231.572 -        case CONSTANT_STRING:
 231.573 -            String sv = stringValue(((CPX)x).cpx, textual);
 231.574 -            if (textual) {
 231.575 -                return '"' + sv + '"';
 231.576 -            } else {
 231.577 -                return sv;
 231.578 -            }
 231.579 -        case CONSTANT_FIELD:
 231.580 -        case CONSTANT_METHOD:
 231.581 -        case CONSTANT_INTERFACEMETHOD:
 231.582 -            //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
 231.583 -             return javaName(getClassName(((CPX2)x).cpx1))+"."+StringValue(((CPX2)x).cpx2);
 231.584 -
 231.585 -        case CONSTANT_NAMEANDTYPE:
 231.586 -            return getName(((CPX2)x).cpx1)+":"+StringValue(((CPX2)x).cpx2);
 231.587 -        default:
 231.588 -            return "UnknownTag"; //TBD
 231.589 -        }
 231.590 -    }
 231.591 -
 231.592 -    /**
 231.593 -     * Returns resolved java type name.
 231.594 -     */
 231.595 -    public String javaName(String name) {
 231.596 -        if( name==null) return "null";
 231.597 -        int len=name.length();
 231.598 -        if (len==0) return "\"\"";
 231.599 -        int cc='/';
 231.600 -    fullname: { // xxx/yyy/zzz
 231.601 -            int cp;
 231.602 -            for (int k=0; k<len; k += Character.charCount(cp)) {
 231.603 -                cp=name.codePointAt(k);
 231.604 -                if (cc=='/') {
 231.605 -                    if (!isJavaIdentifierStart(cp)) break fullname;
 231.606 -                } else if (cp!='/') {
 231.607 -                    if (!isJavaIdentifierPart(cp)) break fullname;
 231.608 -                }
 231.609 -                cc=cp;
 231.610 -            }
 231.611 -            return name;
 231.612 -        }
 231.613 -        return "\""+name+"\"";
 231.614 -    }
 231.615 -
 231.616 -    public String getName(int cpx) {
 231.617 -        String res;
 231.618 -        try {
 231.619 -            return javaName((String)cpool[cpx]); //.replace('/','.');
 231.620 -        } catch (ArrayIndexOutOfBoundsException e) {
 231.621 -            return "<invalid constant pool index:"+cpx+">";
 231.622 -        } catch (ClassCastException e) {
 231.623 -            return "<invalid constant pool ref:"+cpx+">";
 231.624 -        }
 231.625 -    }
 231.626 -
 231.627 -    /**
 231.628 -     * Returns unqualified class name.
 231.629 -     */
 231.630 -    public String getShortClassName(int cpx) {
 231.631 -        String classname=javaName(getClassName(cpx));
 231.632 -        pkgPrefixLen=classname.lastIndexOf("/")+1;
 231.633 -        if (pkgPrefixLen!=0) {
 231.634 -            pkgPrefix=classname.substring(0,pkgPrefixLen);
 231.635 -            if (classname.startsWith(pkgPrefix)) {
 231.636 -                return classname.substring(pkgPrefixLen);
 231.637 -            }
 231.638 -        }
 231.639 -        return classname;
 231.640 -    }
 231.641 -
 231.642 -    /**
 231.643 -     * Returns source file name.
 231.644 -     */
 231.645 -    public String getSourceName(){
 231.646 -        return getName(source_cpx);
 231.647 -    }
 231.648 -
 231.649 -    /**
 231.650 -     * Returns package name.
 231.651 -     */
 231.652 -    public String getPkgName(){
 231.653 -        String classname=getClassName(this_class);
 231.654 -        pkgPrefixLen=classname.lastIndexOf("/")+1;
 231.655 -        if (pkgPrefixLen!=0) {
 231.656 -            pkgPrefix=classname.substring(0,pkgPrefixLen);
 231.657 -            return("package  "+pkgPrefix.substring(0,pkgPrefixLen-1)+";\n");
 231.658 -        }else return null;
 231.659 -    }
 231.660 -
 231.661 -    /**
 231.662 -     * Returns total constant pool entry count.
 231.663 -     */
 231.664 -    public int getCpoolCount(){
 231.665 -        return cpool_count;
 231.666 -    }
 231.667 -
 231.668 -    /**
 231.669 -     * Returns minor version of class file.
 231.670 -     */
 231.671 -    public int getMinor_version(){
 231.672 -        return minor_version;
 231.673 -    }
 231.674 -
 231.675 -    /**
 231.676 -     * Returns major version of class file.
 231.677 -     */
 231.678 -    public int getMajor_version(){
 231.679 -        return major_version;
 231.680 -    }
 231.681 -
 231.682 -    private boolean isJavaIdentifierStart(int cp) {
 231.683 -        return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
 231.684 -    }
 231.685 -
 231.686 -    private boolean isJavaIdentifierPart(int cp) {
 231.687 -        return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
 231.688 -    }
 231.689 -
 231.690 -    public String[] getNameAndType(int indx) {
 231.691 -        return getNameAndType(indx, 0, new String[2]);
 231.692 -    }
 231.693 -    
 231.694 -    private String[] getNameAndType(int indx, int at, String[] arr) {
 231.695 -        CPX2 c2 = getCpoolEntry(indx);
 231.696 -        arr[at] = StringValue(c2.cpx1);
 231.697 -        arr[at + 1] = StringValue(c2.cpx2);
 231.698 -        return arr;
 231.699 -    }
 231.700 -
 231.701 -    public String[] getFieldInfoName(int indx) {
 231.702 -        CPX2 c2 = getCpoolEntry(indx);
 231.703 -        String[] arr = new String[3];
 231.704 -        arr[0] = getClassName(c2.cpx1);
 231.705 -        return getNameAndType(c2.cpx2, 1, arr);
 231.706 -    }
 231.707 -
 231.708 -    static byte[] findAttr(String n, AttrData[] attrs) {
 231.709 -        for (AttrData ad : attrs) {
 231.710 -            if (n.equals(ad.getAttrName())) {
 231.711 -                return ad.getData();
 231.712 -            }
 231.713 -        }
 231.714 -        return null;
 231.715 -    }
 231.716 -}
   232.1 --- a/rt/javap/src/main/java/org/apidesign/javap/Constants.java	Wed Feb 27 17:50:47 2013 +0100
   232.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   232.3 @@ -1,372 +0,0 @@
   232.4 -/*
   232.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   232.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   232.7 - *
   232.8 - * This code is free software; you can redistribute it and/or modify it
   232.9 - * under the terms of the GNU General Public License version 2 only, as
  232.10 - * published by the Free Software Foundation.  Oracle designates this
  232.11 - * particular file as subject to the "Classpath" exception as provided
  232.12 - * by Oracle in the LICENSE file that accompanied this code.
  232.13 - *
  232.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  232.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  232.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  232.17 - * version 2 for more details (a copy is included in the LICENSE file that
  232.18 - * accompanied this code).
  232.19 - *
  232.20 - * You should have received a copy of the GNU General Public License version
  232.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  232.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  232.23 - *
  232.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  232.25 - * or visit www.oracle.com if you need additional information or have any
  232.26 - * questions.
  232.27 - */
  232.28 -
  232.29 -
  232.30 -
  232.31 -package org.apidesign.javap;
  232.32 -
  232.33 -/**
  232.34 - * This interface defines constant that are used
  232.35 - * throughout the compiler. It inherits from RuntimeConstants,
  232.36 - * which is an autogenerated class that contains contstants
  232.37 - * defined in the interpreter.
  232.38 - */
  232.39 -
  232.40 -public
  232.41 -interface Constants extends RuntimeConstants {
  232.42 -
  232.43 -     /**
  232.44 -     * End of input
  232.45 -     */
  232.46 -    public static final int EOF = -1;
  232.47 -
  232.48 -   /*
  232.49 -     * Flags
  232.50 -     */
  232.51 -    public static final int F_VERBOSE           = 1 << 0;
  232.52 -    public static final int F_DUMP              = 1 << 1;
  232.53 -    public static final int F_WARNINGS          = 1 << 2;
  232.54 -    public static final int F_DEBUG             = 1 << 3;
  232.55 -    public static final int F_OPTIMIZE          = 1 << 4;
  232.56 -    public static final int F_DEPENDENCIES      = 1 << 5;
  232.57 -
  232.58 -    /*
  232.59 -     * Type codes
  232.60 -     */
  232.61 -    public static final int TC_BOOLEAN   = 0;
  232.62 -    public static final int TC_BYTE      = 1;
  232.63 -    public static final int TC_CHAR      = 2;
  232.64 -    public static final int TC_SHORT     = 3;
  232.65 -    public static final int TC_INT       = 4;
  232.66 -    public static final int TC_LONG      = 5;
  232.67 -    public static final int TC_FLOAT     = 6;
  232.68 -    public static final int TC_DOUBLE    = 7;
  232.69 -    public static final int TC_NULL      = 8;
  232.70 -    public static final int TC_ARRAY     = 9;
  232.71 -    public static final int TC_CLASS     = 10;
  232.72 -    public static final int TC_VOID      = 11;
  232.73 -    public static final int TC_METHOD    = 12;
  232.74 -    public static final int TC_ERROR     = 13;
  232.75 -
  232.76 -    /*
  232.77 -     * Type Masks
  232.78 -     */
  232.79 -    public static final int TM_NULL      = 1 << TC_NULL;
  232.80 -    public static final int TM_VOID      = 1 << TC_VOID;
  232.81 -    public static final int TM_BOOLEAN   = 1 << TC_BOOLEAN;
  232.82 -    public static final int TM_BYTE      = 1 << TC_BYTE;
  232.83 -    public static final int TM_CHAR      = 1 << TC_CHAR;
  232.84 -    public static final int TM_SHORT     = 1 << TC_SHORT;
  232.85 -    public static final int TM_INT       = 1 << TC_INT;
  232.86 -    public static final int TM_LONG      = 1 << TC_LONG;
  232.87 -    public static final int TM_FLOAT     = 1 << TC_FLOAT;
  232.88 -    public static final int TM_DOUBLE    = 1 << TC_DOUBLE;
  232.89 -    public static final int TM_ARRAY     = 1 << TC_ARRAY;
  232.90 -    public static final int TM_CLASS     = 1 << TC_CLASS;
  232.91 -    public static final int TM_METHOD    = 1 << TC_METHOD;
  232.92 -    public static final int TM_ERROR     = 1 << TC_ERROR;
  232.93 -
  232.94 -    public static final int TM_INT32     = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
  232.95 -    public static final int TM_NUM32     = TM_INT32 | TM_FLOAT;
  232.96 -    public static final int TM_NUM64     = TM_LONG | TM_DOUBLE;
  232.97 -    public static final int TM_INTEGER   = TM_INT32 | TM_LONG;
  232.98 -    public static final int TM_REAL      = TM_FLOAT | TM_DOUBLE;
  232.99 -    public static final int TM_NUMBER    = TM_INTEGER | TM_REAL;
 232.100 -    public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
 232.101 -
 232.102 -    /*
 232.103 -     * Class status
 232.104 -     */
 232.105 -    public static final int CS_UNDEFINED        = 0;
 232.106 -    public static final int CS_UNDECIDED        = 1;
 232.107 -    public static final int CS_BINARY           = 2;
 232.108 -    public static final int CS_SOURCE           = 3;
 232.109 -    public static final int CS_PARSED           = 4;
 232.110 -    public static final int CS_COMPILED         = 5;
 232.111 -    public static final int CS_NOTFOUND         = 6;
 232.112 -
 232.113 -    /*
 232.114 -     * Attributes
 232.115 -     */
 232.116 -    public static final int ATT_ALL             = -1;
 232.117 -    public static final int ATT_CODE            = 1;
 232.118 -
 232.119 -    /*
 232.120 -     * Number of bits used in file offsets
 232.121 -     */
 232.122 -    public static final int OFFSETBITS          = 19;
 232.123 -    public static final int MAXFILESIZE         = (1 << OFFSETBITS) - 1;
 232.124 -    public static final int MAXLINENUMBER       = (1 << (32 - OFFSETBITS)) - 1;
 232.125 -
 232.126 -    /*
 232.127 -     * Operators
 232.128 -     */
 232.129 -    public final int COMMA              = 0;
 232.130 -    public final int ASSIGN             = 1;
 232.131 -
 232.132 -    public final int ASGMUL             = 2;
 232.133 -    public final int ASGDIV             = 3;
 232.134 -    public final int ASGREM             = 4;
 232.135 -    public final int ASGADD             = 5;
 232.136 -    public final int ASGSUB             = 6;
 232.137 -    public final int ASGLSHIFT          = 7;
 232.138 -    public final int ASGRSHIFT          = 8;
 232.139 -    public final int ASGURSHIFT         = 9;
 232.140 -    public final int ASGBITAND          = 10;
 232.141 -    public final int ASGBITOR           = 11;
 232.142 -    public final int ASGBITXOR          = 12;
 232.143 -
 232.144 -    public final int COND               = 13;
 232.145 -    public final int OR                 = 14;
 232.146 -    public final int AND                = 15;
 232.147 -    public final int BITOR              = 16;
 232.148 -    public final int BITXOR             = 17;
 232.149 -    public final int BITAND             = 18;
 232.150 -    public final int NE                 = 19;
 232.151 -    public final int EQ                 = 20;
 232.152 -    public final int GE                 = 21;
 232.153 -    public final int GT                 = 22;
 232.154 -    public final int LE                 = 23;
 232.155 -    public final int LT                 = 24;
 232.156 -    public final int INSTANCEOF         = 25;
 232.157 -    public final int LSHIFT             = 26;
 232.158 -    public final int RSHIFT             = 27;
 232.159 -    public final int URSHIFT            = 28;
 232.160 -    public final int ADD                = 29;
 232.161 -    public final int SUB                = 30;
 232.162 -    public final int DIV                = 31;
 232.163 -    public final int REM                = 32;
 232.164 -    public final int MUL                = 33;
 232.165 -    public final int CAST               = 34;           // (x)y
 232.166 -    public final int POS                = 35;           // +x
 232.167 -    public final int NEG                = 36;           // -x
 232.168 -    public final int NOT                = 37;
 232.169 -    public final int BITNOT             = 38;
 232.170 -    public final int PREINC             = 39;           // ++x
 232.171 -    public final int PREDEC             = 40;           // --x
 232.172 -    public final int NEWARRAY           = 41;
 232.173 -    public final int NEWINSTANCE        = 42;
 232.174 -    public final int NEWFROMNAME        = 43;
 232.175 -    public final int POSTINC            = 44;           // x++
 232.176 -    public final int POSTDEC            = 45;           // x--
 232.177 -    public final int FIELD              = 46;
 232.178 -    public final int METHOD             = 47;           // x(y)
 232.179 -    public final int ARRAYACCESS        = 48;           // x[y]
 232.180 -    public final int NEW                = 49;
 232.181 -    public final int INC                = 50;
 232.182 -    public final int DEC                = 51;
 232.183 -
 232.184 -    public final int CONVERT            = 55;           // implicit conversion
 232.185 -    public final int EXPR               = 56;           // (x)
 232.186 -    public final int ARRAY              = 57;           // {x, y, ...}
 232.187 -    public final int GOTO               = 58;
 232.188 -
 232.189 -    /*
 232.190 -     * Value tokens
 232.191 -     */
 232.192 -    public final int IDENT              = 60;
 232.193 -    public final int BOOLEANVAL         = 61;
 232.194 -    public final int BYTEVAL            = 62;
 232.195 -    public final int CHARVAL            = 63;
 232.196 -    public final int SHORTVAL           = 64;
 232.197 -    public final int INTVAL                     = 65;
 232.198 -    public final int LONGVAL            = 66;
 232.199 -    public final int FLOATVAL           = 67;
 232.200 -    public final int DOUBLEVAL          = 68;
 232.201 -    public final int STRINGVAL          = 69;
 232.202 -
 232.203 -    /*
 232.204 -     * Type keywords
 232.205 -     */
 232.206 -    public final int BYTE               = 70;
 232.207 -    public final int CHAR               = 71;
 232.208 -    public final int SHORT              = 72;
 232.209 -    public final int INT                = 73;
 232.210 -    public final int LONG               = 74;
 232.211 -    public final int FLOAT              = 75;
 232.212 -    public final int DOUBLE             = 76;
 232.213 -    public final int VOID               = 77;
 232.214 -    public final int BOOLEAN            = 78;
 232.215 -
 232.216 -    /*
 232.217 -     * Expression keywords
 232.218 -     */
 232.219 -    public final int TRUE               = 80;
 232.220 -    public final int FALSE              = 81;
 232.221 -    public final int THIS               = 82;
 232.222 -    public final int SUPER              = 83;
 232.223 -    public final int NULL               = 84;
 232.224 -
 232.225 -    /*
 232.226 -     * Statement keywords
 232.227 -     */
 232.228 -    public final int IF                 = 90;
 232.229 -    public final int ELSE               = 91;
 232.230 -    public final int FOR                = 92;
 232.231 -    public final int WHILE              = 93;
 232.232 -    public final int DO                 = 94;
 232.233 -    public final int SWITCH             = 95;
 232.234 -    public final int CASE               = 96;
 232.235 -    public final int DEFAULT            = 97;
 232.236 -    public final int BREAK              = 98;
 232.237 -    public final int CONTINUE           = 99;
 232.238 -    public final int RETURN             = 100;
 232.239 -    public final int TRY                = 101;
 232.240 -    public final int CATCH              = 102;
 232.241 -    public final int FINALLY            = 103;
 232.242 -    public final int THROW              = 104;
 232.243 -    public final int STAT               = 105;
 232.244 -    public final int EXPRESSION         = 106;
 232.245 -    public final int DECLARATION        = 107;
 232.246 -    public final int VARDECLARATION     = 108;
 232.247 -
 232.248 -    /*
 232.249 -     * Declaration keywords
 232.250 -     */
 232.251 -    public final int IMPORT             = 110;
 232.252 -    public final int CLASS              = 111;
 232.253 -    public final int EXTENDS            = 112;
 232.254 -    public final int IMPLEMENTS         = 113;
 232.255 -    public final int INTERFACE          = 114;
 232.256 -    public final int PACKAGE            = 115;
 232.257 -
 232.258 -    /*
 232.259 -     * Modifier keywords
 232.260 -     */
 232.261 -    public final int PRIVATE    = 120;
 232.262 -    public final int PUBLIC             = 121;
 232.263 -    public final int PROTECTED  = 122;
 232.264 -    public final int CONST              = 123;
 232.265 -    public final int STATIC             = 124;
 232.266 -    public final int TRANSIENT          = 125;
 232.267 -    public final int SYNCHRONIZED       = 126;
 232.268 -    public final int NATIVE             = 127;
 232.269 -    public final int FINAL              = 128;
 232.270 -    public final int VOLATILE   = 129;
 232.271 -    public final int ABSTRACT   = 130;
 232.272 -    public final int STRICT             = 165;
 232.273 -
 232.274 -    /*
 232.275 -     * Punctuation
 232.276 -     */
 232.277 -    public final int SEMICOLON  = 135;
 232.278 -    public final int COLON              = 136;
 232.279 -    public final int QUESTIONMARK       = 137;
 232.280 -    public final int LBRACE             = 138;
 232.281 -    public final int RBRACE             = 139;
 232.282 -    public final int LPAREN             = 140;
 232.283 -    public final int RPAREN             = 141;
 232.284 -    public final int LSQBRACKET = 142;
 232.285 -    public final int RSQBRACKET = 143;
 232.286 -    public final int THROWS     = 144;
 232.287 -
 232.288 -    /*
 232.289 -     * Special tokens
 232.290 -     */
 232.291 -    public final int ERROR              = 145;          // an error
 232.292 -    public final int COMMENT    = 146;          // not used anymore.
 232.293 -    public final int TYPE               = 147;
 232.294 -    public final int LENGTH             = 148;
 232.295 -    public final int INLINERETURN       = 149;
 232.296 -    public final int INLINEMETHOD       = 150;
 232.297 -    public final int INLINENEWINSTANCE  = 151;
 232.298 -
 232.299 -    /*
 232.300 -     * Added for jasm
 232.301 -     */
 232.302 -        public final int METHODREF      = 152;
 232.303 -        public final int FIELDREF       = 153;
 232.304 -    public final int STACK              = 154;
 232.305 -    public final int LOCAL              = 155;
 232.306 -    public final int CPINDEX    = 156;
 232.307 -    public final int CPNAME             = 157;
 232.308 -    public final int SIGN               = 158;
 232.309 -    public final int BITS               = 159;
 232.310 -    public final int INF                = 160;
 232.311 -    public final int NAN                = 161;
 232.312 -    public final int INNERCLASS = 162;
 232.313 -    public final int OF         = 163;
 232.314 -    public final int SYNTHETIC          = 164;
 232.315 -// last used=165;
 232.316 -
 232.317 -   /*
 232.318 -     * Operator precedence
 232.319 -     */
 232.320 -    public static final int opPrecedence[] = {
 232.321 -        10,     11,     11,     11,     11,     11,     11,     11,     11,     11,
 232.322 -        11,     11,     11,     12,     13,     14,     15,     16,     17,     18,
 232.323 -        18,     19,     19,     19,     19,     19,     20,     20,     20,     21,
 232.324 -        21,     22,     22,     22,     23,     24,     24,     24,     24,     24,
 232.325 -        24,     25,     25,     26,     26,     26,     26,     26,     26
 232.326 -    };
 232.327 -
 232.328 -    /*
 232.329 -     * Operator names
 232.330 -     */
 232.331 -    public static final String opNames[] = {
 232.332 -        ",",            "=",            "*=",           "/=",           "%=",
 232.333 -        "+=",           "-=",           "<<=",          ">>=",          "<<<=",
 232.334 -        "&=",           "|=",           "^=",           "?:",           "||",
 232.335 -        "&&",           "|",            "^",            "&",            "!=",
 232.336 -        "==",           ">=",           ">",            "<=",           "<",
 232.337 -        "instanceof",   "<<",           ">>",           "<<<",          "+",
 232.338 -        "-",            "/",            "%",            "*",            "cast",
 232.339 -        "+",            "-",            "!",            "~",            "++",
 232.340 -        "--",           "new",          "new",          "new",          "++",
 232.341 -        "--",           "field",        "method",       "[]",           "new",
 232.342 -        "++",           "--",           null,           null,           null,
 232.343 -
 232.344 -        "convert",      "expr",         "array",        "goto",         null,
 232.345 -
 232.346 -        "Identifier",   "Boolean",      "Byte",         "Char",         "Short",
 232.347 -        "Integer",              "Long",         "Float",        "Double",       "String",
 232.348 -
 232.349 -        "byte",         "char",         "short",        "int",          "long",
 232.350 -        "float",        "double",       "void",         "boolean",      null,
 232.351 -
 232.352 -        "true",         "false",        "this",         "super",        "null",
 232.353 -        null,           null,           null,           null,           null,
 232.354 -
 232.355 -        "if",           "else",         "for",          "while",        "do",
 232.356 -        "switch",       "case",         "default",      "break",        "continue",
 232.357 -        "return",       "try",          "catch",        "finally",      "throw",
 232.358 -        "stat",         "expression",   "declaration",  "declaration",  null,
 232.359 -
 232.360 -        "import",       "class",        "extends",      "implements",   "interface",
 232.361 -        "package",      null,           null,           null,           null,
 232.362 -
 232.363 -        "private",      "public",       "protected",    "const",        "static",
 232.364 -        "transient",    "synchronized", "native",       "final",        "volatile",
 232.365 -        "abstract",     null,           null,           null,           null,
 232.366 -
 232.367 -        ";",            ":",            "?",            "{",            "}",
 232.368 -        "(",            ")",            "[",            "]",            "throws",
 232.369 -        "error",        "comment",      "type",         "length",       "inline-return",
 232.370 -        "inline-method", "inline-new",
 232.371 -        "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN",
 232.372 -        "bits", "INF", "NaN", "InnerClass", "of", "synthetic"
 232.373 -    };
 232.374 -
 232.375 -}
   233.1 --- a/rt/javap/src/main/java/org/apidesign/javap/FieldData.java	Wed Feb 27 17:50:47 2013 +0100
   233.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   233.3 @@ -1,168 +0,0 @@
   233.4 -/*
   233.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   233.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   233.7 - *
   233.8 - * This code is free software; you can redistribute it and/or modify it
   233.9 - * under the terms of the GNU General Public License version 2 only, as
  233.10 - * published by the Free Software Foundation.  Oracle designates this
  233.11 - * particular file as subject to the "Classpath" exception as provided
  233.12 - * by Oracle in the LICENSE file that accompanied this code.
  233.13 - *
  233.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  233.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  233.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  233.17 - * version 2 for more details (a copy is included in the LICENSE file that
  233.18 - * accompanied this code).
  233.19 - *
  233.20 - * You should have received a copy of the GNU General Public License version
  233.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  233.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  233.23 - *
  233.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  233.25 - * or visit www.oracle.com if you need additional information or have any
  233.26 - * questions.
  233.27 - */
  233.28 -
  233.29 -
  233.30 -package org.apidesign.javap;
  233.31 -
  233.32 -import java.io.*;
  233.33 -
  233.34 -/**
  233.35 - * Strores field data informastion.
  233.36 - *
  233.37 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  233.38 - */
  233.39 -
  233.40 -public class FieldData implements RuntimeConstants  {
  233.41 -
  233.42 -    ClassData cls;
  233.43 -    int access;
  233.44 -    int name_index;
  233.45 -    int descriptor_index;
  233.46 -    int attributes_count;
  233.47 -    int value_cpx=0;
  233.48 -    boolean isSynthetic=false;
  233.49 -    boolean isDeprecated=false;
  233.50 -    Vector attrs;
  233.51 -
  233.52 -    public FieldData(ClassData cls){
  233.53 -        this.cls=cls;
  233.54 -    }
  233.55 -
  233.56 -    /**
  233.57 -     * Read and store field info.
  233.58 -     */
  233.59 -    public void read(DataInputStream in) throws IOException {
  233.60 -        access = in.readUnsignedShort();
  233.61 -        name_index = in.readUnsignedShort();
  233.62 -        descriptor_index = in.readUnsignedShort();
  233.63 -        // Read the attributes
  233.64 -        int attributes_count = in.readUnsignedShort();
  233.65 -        attrs=new Vector(attributes_count);
  233.66 -        for (int i = 0; i < attributes_count; i++) {
  233.67 -            int attr_name_index=in.readUnsignedShort();
  233.68 -            if (cls.getTag(attr_name_index)!=CONSTANT_UTF8) continue;
  233.69 -            String attr_name=cls.getString(attr_name_index);
  233.70 -            if (attr_name.equals("ConstantValue")){
  233.71 -                if (in.readInt()!=2)
  233.72 -                    throw new ClassFormatError("invalid ConstantValue attr length");
  233.73 -                value_cpx=in.readUnsignedShort();
  233.74 -                AttrData attr=new AttrData(cls);
  233.75 -                attr.read(attr_name_index);
  233.76 -                attrs.addElement(attr);
  233.77 -            } else if (attr_name.equals("Synthetic")){
  233.78 -                if (in.readInt()!=0)
  233.79 -                    throw new ClassFormatError("invalid Synthetic attr length");
  233.80 -                isSynthetic=true;
  233.81 -                AttrData attr=new AttrData(cls);
  233.82 -                attr.read(attr_name_index);
  233.83 -                attrs.addElement(attr);
  233.84 -            } else if (attr_name.equals("Deprecated")){
  233.85 -                if (in.readInt()!=0)
  233.86 -                    throw new ClassFormatError("invalid Synthetic attr length");
  233.87 -                isDeprecated = true;
  233.88 -                AttrData attr=new AttrData(cls);
  233.89 -                attr.read(attr_name_index);
  233.90 -                attrs.addElement(attr);
  233.91 -            } else {
  233.92 -                AttrData attr=new AttrData(cls);
  233.93 -                attr.read(attr_name_index, in);
  233.94 -                attrs.addElement(attr);
  233.95 -            }
  233.96 -        }
  233.97 -
  233.98 -    }  // end read
  233.99 -
 233.100 -    public boolean isStatic() {
 233.101 -        return (access & ACC_STATIC) != 0;
 233.102 -    }
 233.103 -    
 233.104 -    /**
 233.105 -     * Returns access of a field.
 233.106 -     */
 233.107 -    public String[] getAccess(){
 233.108 -        Vector v = new Vector();
 233.109 -        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
 233.110 -        if ((access & ACC_PRIVATE)   !=0) v.addElement("private");
 233.111 -        if ((access & ACC_PROTECTED)   !=0) v.addElement("protected");
 233.112 -        if ((access & ACC_STATIC)   !=0) v.addElement("static");
 233.113 -        if ((access & ACC_FINAL)    !=0) v.addElement("final");
 233.114 -        if ((access & ACC_VOLATILE) !=0) v.addElement("volatile");
 233.115 -        if ((access & ACC_TRANSIENT) !=0) v.addElement("transient");
 233.116 -        String[] accflags = new String[v.size()];
 233.117 -        v.copyInto(accflags);
 233.118 -        return accflags;
 233.119 -    }
 233.120 -
 233.121 -    /**
 233.122 -     * Returns name of a field.
 233.123 -     */
 233.124 -    public String getName(){
 233.125 -        return cls.getStringValue(name_index);
 233.126 -    }
 233.127 -
 233.128 -    /**
 233.129 -     * Returns internal signature of a field
 233.130 -     */
 233.131 -    public String getInternalSig(){
 233.132 -        return cls.getStringValue(descriptor_index);
 233.133 -    }
 233.134 -
 233.135 -    /**
 233.136 -     * Returns true if field is synthetic.
 233.137 -     */
 233.138 -    public boolean isSynthetic(){
 233.139 -        return isSynthetic;
 233.140 -    }
 233.141 -
 233.142 -    /**
 233.143 -     * Returns true if field is deprecated.
 233.144 -     */
 233.145 -    public boolean isDeprecated(){
 233.146 -        return isDeprecated;
 233.147 -    }
 233.148 -
 233.149 -    /**
 233.150 -     * Returns index of constant value in cpool.
 233.151 -     */
 233.152 -    public int getConstantValueIndex(){
 233.153 -        return (value_cpx);
 233.154 -    }
 233.155 -
 233.156 -    /**
 233.157 -     * Returns list of attributes of field.
 233.158 -     */
 233.159 -    public Vector getAttributes(){
 233.160 -        return attrs;
 233.161 -    }
 233.162 -
 233.163 -    public byte[] findAnnotationData(boolean classRetention) {
 233.164 -        String n = classRetention ?
 233.165 -            "RuntimeInvisibleAnnotations" : // NOI18N
 233.166 -            "RuntimeVisibleAnnotations"; // NOI18N
 233.167 -        AttrData[] arr = new AttrData[attrs.size()];
 233.168 -        attrs.copyInto(arr);
 233.169 -        return ClassData.findAttr(n, arr);
 233.170 -    }
 233.171 -}
   234.1 --- a/rt/javap/src/main/java/org/apidesign/javap/Hashtable.java	Wed Feb 27 17:50:47 2013 +0100
   234.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   234.3 @@ -1,94 +0,0 @@
   234.4 -/**
   234.5 - * Back 2 Browser Bytecode Translator
   234.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   234.7 - *
   234.8 - * This program is free software: you can redistribute it and/or modify
   234.9 - * it under the terms of the GNU General Public License as published by
  234.10 - * the Free Software Foundation, version 2 of the License.
  234.11 - *
  234.12 - * This program is distributed in the hope that it will be useful,
  234.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  234.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  234.15 - * GNU General Public License for more details.
  234.16 - *
  234.17 - * You should have received a copy of the GNU General Public License
  234.18 - * along with this program. Look for COPYING file in the top folder.
  234.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  234.20 - */
  234.21 -package org.apidesign.javap;
  234.22 -
  234.23 -/** A JavaScript optimized replacement for Hashtable.
  234.24 - *
  234.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  234.26 - */
  234.27 -final class Hashtable {
  234.28 -    private Object[] keys;
  234.29 -    private Object[] values;
  234.30 -
  234.31 -    Hashtable(int i) {
  234.32 -        this();
  234.33 -    }
  234.34 -
  234.35 -    Hashtable(int i, double d) {
  234.36 -        this();
  234.37 -    }
  234.38 -
  234.39 -    Hashtable() {
  234.40 -    }
  234.41 -
  234.42 -    synchronized void put(Object key, Object val) {
  234.43 -        int[] where = { -1, -1 };
  234.44 -        Object found = get(key, where);
  234.45 -        if (where[0] != -1) {
  234.46 -            // key exists
  234.47 -            values[where[0]] = val;
  234.48 -        } else {
  234.49 -            if (where[1] != -1) {
  234.50 -                // null found
  234.51 -                keys[where[1]] = key;
  234.52 -                values[where[1]] = val;
  234.53 -            } else {
  234.54 -                if (keys == null) {
  234.55 -                    keys = new Object[11];
  234.56 -                    values = new Object[11];
  234.57 -                    keys[0] = key;
  234.58 -                    values[0] = val;
  234.59 -                } else {
  234.60 -                    Object[] newKeys = new Object[keys.length * 2];
  234.61 -                    Object[] newValues = new Object[values.length * 2];
  234.62 -                    for (int i = 0; i < keys.length; i++) {
  234.63 -                        newKeys[i] = keys[i];
  234.64 -                        newValues[i] = values[i];
  234.65 -                    }
  234.66 -                    newKeys[keys.length] = key;
  234.67 -                    newValues[keys.length] = val;
  234.68 -                    keys = newKeys;
  234.69 -                    values = newValues;
  234.70 -                }
  234.71 -            }
  234.72 -        }
  234.73 -    }
  234.74 -
  234.75 -    Object get(Object key) {
  234.76 -        return get(key, null);
  234.77 -    }
  234.78 -    private synchronized Object get(Object key, int[] foundAndNull) {
  234.79 -        if (keys == null) {
  234.80 -            return null;
  234.81 -        }
  234.82 -        for (int i = 0; i < keys.length; i++) {
  234.83 -            if (keys[i] == null) {
  234.84 -                if (foundAndNull != null) {
  234.85 -                    foundAndNull[1] = i;
  234.86 -                }
  234.87 -            } else if (keys[i].equals(key)) {
  234.88 -                if (foundAndNull != null) {
  234.89 -                    foundAndNull[0] = i;
  234.90 -                }
  234.91 -                return values[i];
  234.92 -            }
  234.93 -        }
  234.94 -        return null;
  234.95 -    }
  234.96 -    
  234.97 -}
   235.1 --- a/rt/javap/src/main/java/org/apidesign/javap/InnerClassData.java	Wed Feb 27 17:50:47 2013 +0100
   235.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   235.3 @@ -1,75 +0,0 @@
   235.4 -/*
   235.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   235.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   235.7 - *
   235.8 - * This code is free software; you can redistribute it and/or modify it
   235.9 - * under the terms of the GNU General Public License version 2 only, as
  235.10 - * published by the Free Software Foundation.  Oracle designates this
  235.11 - * particular file as subject to the "Classpath" exception as provided
  235.12 - * by Oracle in the LICENSE file that accompanied this code.
  235.13 - *
  235.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  235.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  235.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  235.17 - * version 2 for more details (a copy is included in the LICENSE file that
  235.18 - * accompanied this code).
  235.19 - *
  235.20 - * You should have received a copy of the GNU General Public License version
  235.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  235.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  235.23 - *
  235.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  235.25 - * or visit www.oracle.com if you need additional information or have any
  235.26 - * questions.
  235.27 - */
  235.28 -
  235.29 -
  235.30 -package org.apidesign.javap;
  235.31 -
  235.32 -import java.io.*;
  235.33 -import java.util.*;
  235.34 -
  235.35 -/**
  235.36 - * Strores InnerClass data informastion.
  235.37 - *
  235.38 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  235.39 - */
  235.40 -class InnerClassData  implements RuntimeConstants {
  235.41 -    ClassData cls;
  235.42 -
  235.43 -
  235.44 -    int inner_class_info_index
  235.45 -        ,outer_class_info_index
  235.46 -        ,inner_name_index
  235.47 -        ,access
  235.48 -        ;
  235.49 -
  235.50 -    public InnerClassData(ClassData cls) {
  235.51 -        this.cls=cls;
  235.52 -
  235.53 -    }
  235.54 -
  235.55 -    /**
  235.56 -     * Read Innerclass attribute data.
  235.57 -     */
  235.58 -    public void read(DataInputStream in) throws IOException {
  235.59 -        inner_class_info_index = in.readUnsignedShort();
  235.60 -        outer_class_info_index = in.readUnsignedShort();
  235.61 -        inner_name_index = in.readUnsignedShort();
  235.62 -        access = in.readUnsignedShort();
  235.63 -    }  // end read
  235.64 -
  235.65 -    /**
  235.66 -     * Returns the access of this class or interface.
  235.67 -     */
  235.68 -    public String[] getAccess(){
  235.69 -        Vector v = new Vector();
  235.70 -        if ((access & ACC_PUBLIC)   !=0) v.addElement("public");
  235.71 -        if ((access & ACC_FINAL)    !=0) v.addElement("final");
  235.72 -        if ((access & ACC_ABSTRACT) !=0) v.addElement("abstract");
  235.73 -        String[] accflags = new String[v.size()];
  235.74 -        v.copyInto(accflags);
  235.75 -        return accflags;
  235.76 -    }
  235.77 -
  235.78 -} // end InnerClassData
   236.1 --- a/rt/javap/src/main/java/org/apidesign/javap/LineNumData.java	Wed Feb 27 17:50:47 2013 +0100
   236.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   236.3 @@ -1,50 +0,0 @@
   236.4 -/*
   236.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   236.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   236.7 - *
   236.8 - * This code is free software; you can redistribute it and/or modify it
   236.9 - * under the terms of the GNU General Public License version 2 only, as
  236.10 - * published by the Free Software Foundation.  Oracle designates this
  236.11 - * particular file as subject to the "Classpath" exception as provided
  236.12 - * by Oracle in the LICENSE file that accompanied this code.
  236.13 - *
  236.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  236.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  236.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  236.17 - * version 2 for more details (a copy is included in the LICENSE file that
  236.18 - * accompanied this code).
  236.19 - *
  236.20 - * You should have received a copy of the GNU General Public License version
  236.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  236.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  236.23 - *
  236.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  236.25 - * or visit www.oracle.com if you need additional information or have any
  236.26 - * questions.
  236.27 - */
  236.28 -
  236.29 -
  236.30 -package org.apidesign.javap;
  236.31 -
  236.32 -import java.util.*;
  236.33 -import java.io.*;
  236.34 -
  236.35 -/**
  236.36 - * Strores LineNumberTable data information.
  236.37 - *
  236.38 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  236.39 - */
  236.40 -class LineNumData {
  236.41 -    short start_pc, line_number;
  236.42 -
  236.43 -    public LineNumData() {}
  236.44 -
  236.45 -    /**
  236.46 -     * Read LineNumberTable attribute.
  236.47 -     */
  236.48 -    public LineNumData(DataInputStream in) throws IOException {
  236.49 -        start_pc = in.readShort();
  236.50 -        line_number=in.readShort();
  236.51 -
  236.52 -    }
  236.53 -}
   237.1 --- a/rt/javap/src/main/java/org/apidesign/javap/LocVarData.java	Wed Feb 27 17:50:47 2013 +0100
   237.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   237.3 @@ -1,54 +0,0 @@
   237.4 -/*
   237.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   237.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   237.7 - *
   237.8 - * This code is free software; you can redistribute it and/or modify it
   237.9 - * under the terms of the GNU General Public License version 2 only, as
  237.10 - * published by the Free Software Foundation.  Oracle designates this
  237.11 - * particular file as subject to the "Classpath" exception as provided
  237.12 - * by Oracle in the LICENSE file that accompanied this code.
  237.13 - *
  237.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  237.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  237.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  237.17 - * version 2 for more details (a copy is included in the LICENSE file that
  237.18 - * accompanied this code).
  237.19 - *
  237.20 - * You should have received a copy of the GNU General Public License version
  237.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  237.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  237.23 - *
  237.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  237.25 - * or visit www.oracle.com if you need additional information or have any
  237.26 - * questions.
  237.27 - */
  237.28 -
  237.29 -
  237.30 -package org.apidesign.javap;
  237.31 -
  237.32 -import java.util.*;
  237.33 -import java.io.*;
  237.34 -
  237.35 -/**
  237.36 - * Strores LocalVariableTable data information.
  237.37 - *
  237.38 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  237.39 - */
  237.40 -class LocVarData {
  237.41 -    short start_pc, length, name_cpx, sig_cpx, slot;
  237.42 -
  237.43 -    public LocVarData() {
  237.44 -    }
  237.45 -
  237.46 -    /**
  237.47 -     * Read LocalVariableTable attribute.
  237.48 -     */
  237.49 -    public LocVarData(DataInputStream in) throws IOException {
  237.50 -        start_pc = in.readShort();
  237.51 -        length=in.readShort();
  237.52 -        name_cpx=in.readShort();
  237.53 -        sig_cpx=in.readShort();
  237.54 -        slot=in.readShort();
  237.55 -
  237.56 -    }
  237.57 -}
   238.1 --- a/rt/javap/src/main/java/org/apidesign/javap/MethodData.java	Wed Feb 27 17:50:47 2013 +0100
   238.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   238.3 @@ -1,394 +0,0 @@
   238.4 -/*
   238.5 - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
   238.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   238.7 - *
   238.8 - * This code is free software; you can redistribute it and/or modify it
   238.9 - * under the terms of the GNU General Public License version 2 only, as
  238.10 - * published by the Free Software Foundation.  Oracle designates this
  238.11 - * particular file as subject to the "Classpath" exception as provided
  238.12 - * by Oracle in the LICENSE file that accompanied this code.
  238.13 - *
  238.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  238.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  238.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  238.17 - * version 2 for more details (a copy is included in the LICENSE file that
  238.18 - * accompanied this code).
  238.19 - *
  238.20 - * You should have received a copy of the GNU General Public License version
  238.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  238.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  238.23 - *
  238.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  238.25 - * or visit www.oracle.com if you need additional information or have any
  238.26 - * questions.
  238.27 - */
  238.28 -
  238.29 -package org.apidesign.javap;
  238.30 -
  238.31 -
  238.32 -import java.io.DataInputStream;
  238.33 -import java.io.IOException;
  238.34 -import static org.apidesign.javap.RuntimeConstants.*;
  238.35 -
  238.36 -/**
  238.37 - * Strores method data informastion.
  238.38 - *
  238.39 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  238.40 - */
  238.41 -public class MethodData {
  238.42 -
  238.43 -    ClassData cls;
  238.44 -    int access;
  238.45 -    int name_index;
  238.46 -    int descriptor_index;
  238.47 -    int attributes_count;
  238.48 -    byte[] code;
  238.49 -    Vector exception_table = new Vector(0);
  238.50 -    Vector lin_num_tb = new Vector(0);
  238.51 -    Vector loc_var_tb = new Vector(0);
  238.52 -    StackMapTableData[] stackMapTable;
  238.53 -    StackMapData[] stackMap;
  238.54 -    int[] exc_index_table=null;
  238.55 -    Vector attrs=new Vector(0);
  238.56 -    Vector code_attrs=new Vector(0);
  238.57 -    int max_stack,  max_locals;
  238.58 -    boolean isSynthetic=false;
  238.59 -    boolean isDeprecated=false;
  238.60 -
  238.61 -    public MethodData(ClassData cls){
  238.62 -        this.cls=cls;
  238.63 -    }
  238.64 -
  238.65 -    /**
  238.66 -     * Read method info.
  238.67 -     */
  238.68 -    public void read(DataInputStream in) throws IOException {
  238.69 -        access = in.readUnsignedShort();
  238.70 -        name_index=in.readUnsignedShort();
  238.71 -        descriptor_index =in.readUnsignedShort();
  238.72 -        int attributes_count = in.readUnsignedShort();
  238.73 -        for (int i = 0; i < attributes_count; i++) {
  238.74 -            int attr_name_index=in.readUnsignedShort();
  238.75 -
  238.76 -        readAttr: {
  238.77 -                if (cls.getTag(attr_name_index)==CONSTANT_UTF8) {
  238.78 -                    String  attr_name=cls.getString(attr_name_index);
  238.79 -                    if ( attr_name.equals("Code")){
  238.80 -                        readCode (in);
  238.81 -                        AttrData attr=new AttrData(cls);
  238.82 -                        attr.read(attr_name_index);
  238.83 -                        attrs.addElement(attr);
  238.84 -                        break readAttr;
  238.85 -                    } else if ( attr_name.equals("Exceptions")){
  238.86 -                        readExceptions(in);
  238.87 -                        AttrData attr=new AttrData(cls);
  238.88 -                        attr.read(attr_name_index);
  238.89 -                        attrs.addElement(attr);
  238.90 -                        break readAttr;
  238.91 -                    } else if (attr_name.equals("Synthetic")){
  238.92 -                        if (in.readInt()!=0)
  238.93 -                            throw new ClassFormatError("invalid Synthetic attr length");
  238.94 -                        isSynthetic=true;
  238.95 -                        AttrData attr=new AttrData(cls);
  238.96 -                        attr.read(attr_name_index);
  238.97 -                        attrs.addElement(attr);
  238.98 -                        break readAttr;
  238.99 -                    } else if (attr_name.equals("Deprecated")){
 238.100 -                        if (in.readInt()!=0)
 238.101 -                            throw new ClassFormatError("invalid Synthetic attr length");
 238.102 -                        isDeprecated = true;
 238.103 -                        AttrData attr=new AttrData(cls);
 238.104 -                        attr.read(attr_name_index);
 238.105 -                        attrs.addElement(attr);
 238.106 -                        break readAttr;
 238.107 -                    }
 238.108 -                }
 238.109 -                AttrData attr=new AttrData(cls);
 238.110 -                attr.read(attr_name_index, in);
 238.111 -                attrs.addElement(attr);
 238.112 -            }
 238.113 -        }
 238.114 -    }
 238.115 -
 238.116 -    /**
 238.117 -     * Read code attribute info.
 238.118 -     */
 238.119 -    public void readCode(DataInputStream in) throws IOException {
 238.120 -
 238.121 -        int attr_length = in.readInt();
 238.122 -        max_stack=in.readUnsignedShort();
 238.123 -        max_locals=in.readUnsignedShort();
 238.124 -        int codelen=in.readInt();
 238.125 -
 238.126 -        code=new byte[codelen];
 238.127 -        int totalread = 0;
 238.128 -        while(totalread < codelen){
 238.129 -            totalread += in.read(code, totalread, codelen-totalread);
 238.130 -        }
 238.131 -        //      in.read(code, 0, codelen);
 238.132 -        int clen = 0;
 238.133 -        readExceptionTable(in);
 238.134 -        int code_attributes_count = in.readUnsignedShort();
 238.135 -
 238.136 -        for (int k = 0 ; k < code_attributes_count ; k++) {
 238.137 -            int table_name_index=in.readUnsignedShort();
 238.138 -            int table_name_tag=cls.getTag(table_name_index);
 238.139 -            AttrData attr=new AttrData(cls);
 238.140 -            if (table_name_tag==CONSTANT_UTF8) {
 238.141 -                String table_name_tstr=cls.getString(table_name_index);
 238.142 -                if (table_name_tstr.equals("LineNumberTable")) {
 238.143 -                    readLineNumTable(in);
 238.144 -                    attr.read(table_name_index);
 238.145 -                } else if (table_name_tstr.equals("LocalVariableTable")) {
 238.146 -                    readLocVarTable(in);
 238.147 -                    attr.read(table_name_index);
 238.148 -                } else if (table_name_tstr.equals("StackMapTable")) {
 238.149 -                    readStackMapTable(in);
 238.150 -                    attr.read(table_name_index);
 238.151 -                } else if (table_name_tstr.equals("StackMap")) {
 238.152 -                    readStackMap(in);
 238.153 -                    attr.read(table_name_index);
 238.154 -                } else {
 238.155 -                    attr.read(table_name_index, in);
 238.156 -                }
 238.157 -                code_attrs.addElement(attr);
 238.158 -                continue;
 238.159 -            }
 238.160 -
 238.161 -            attr.read(table_name_index, in);
 238.162 -            code_attrs.addElement(attr);
 238.163 -        }
 238.164 -    }
 238.165 -
 238.166 -    /**
 238.167 -     * Read exception table info.
 238.168 -     */
 238.169 -    void readExceptionTable (DataInputStream in) throws IOException {
 238.170 -        int exception_table_len=in.readUnsignedShort();
 238.171 -        exception_table=new Vector(exception_table_len);
 238.172 -        for (int l = 0; l < exception_table_len; l++) {
 238.173 -            exception_table.addElement(new TrapData(in, l));
 238.174 -        }
 238.175 -    }
 238.176 -
 238.177 -    /**
 238.178 -     * Read LineNumberTable attribute info.
 238.179 -     */
 238.180 -    void readLineNumTable (DataInputStream in) throws IOException {
 238.181 -        int attr_len = in.readInt(); // attr_length
 238.182 -        int lin_num_tb_len = in.readUnsignedShort();
 238.183 -        lin_num_tb=new Vector(lin_num_tb_len);
 238.184 -        for (int l = 0; l < lin_num_tb_len; l++) {
 238.185 -            lin_num_tb.addElement(new LineNumData(in));
 238.186 -        }
 238.187 -    }
 238.188 -
 238.189 -    /**
 238.190 -     * Read LocalVariableTable attribute info.
 238.191 -     */
 238.192 -    void readLocVarTable (DataInputStream in) throws IOException {
 238.193 -        int attr_len=in.readInt(); // attr_length
 238.194 -        int loc_var_tb_len = in.readUnsignedShort();
 238.195 -        loc_var_tb = new Vector(loc_var_tb_len);
 238.196 -        for (int l = 0; l < loc_var_tb_len; l++) {
 238.197 -            loc_var_tb.addElement(new LocVarData(in));
 238.198 -        }
 238.199 -    }
 238.200 -
 238.201 -    /**
 238.202 -     * Read Exception attribute info.
 238.203 -     */
 238.204 -    public void readExceptions(DataInputStream in) throws IOException {
 238.205 -        int attr_len=in.readInt(); // attr_length in prog
 238.206 -        int num_exceptions = in.readUnsignedShort();
 238.207 -        exc_index_table=new int[num_exceptions];
 238.208 -        for (int l = 0; l < num_exceptions; l++) {
 238.209 -            int exc=in.readShort();
 238.210 -            exc_index_table[l]=exc;
 238.211 -        }
 238.212 -    }
 238.213 -
 238.214 -    /**
 238.215 -     * Read StackMapTable attribute info.
 238.216 -     */
 238.217 -    void readStackMapTable(DataInputStream in) throws IOException {
 238.218 -        int attr_len = in.readInt();  //attr_length
 238.219 -        int stack_map_tb_len = in.readUnsignedShort();
 238.220 -        stackMapTable = new StackMapTableData[stack_map_tb_len];
 238.221 -        for (int i=0; i<stack_map_tb_len; i++) {
 238.222 -            stackMapTable[i] = StackMapTableData.getInstance(in, this);
 238.223 -        }
 238.224 -    }
 238.225 -
 238.226 -    /**
 238.227 -     * Read StackMap attribute info.
 238.228 -     */
 238.229 -    void readStackMap(DataInputStream in) throws IOException {
 238.230 -        int attr_len = in.readInt();  //attr_length
 238.231 -        int stack_map_len = in.readUnsignedShort();
 238.232 -        stackMap = new StackMapData[stack_map_len];
 238.233 -        for (int i = 0; i<stack_map_len; i++) {
 238.234 -            stackMap[i] = new StackMapData(in, this);
 238.235 -        }
 238.236 -    }
 238.237 -
 238.238 -    /**
 238.239 -     * Return access of the method.
 238.240 -     */
 238.241 -    public int getAccess(){
 238.242 -        return access;
 238.243 -    }
 238.244 -
 238.245 -    /**
 238.246 -     * Return name of the method.
 238.247 -     */
 238.248 -    public String getName(){
 238.249 -        return cls.getStringValue(name_index);
 238.250 -    }
 238.251 -
 238.252 -    /**
 238.253 -     * Return internal siganature of the method.
 238.254 -     */
 238.255 -    public String getInternalSig(){
 238.256 -        return cls.getStringValue(descriptor_index);
 238.257 -    }
 238.258 -
 238.259 -    /**
 238.260 -     * Return code attribute data of a method.
 238.261 -     */
 238.262 -    public byte[] getCode(){
 238.263 -        return code;
 238.264 -    }
 238.265 -
 238.266 -    /**
 238.267 -     * Return LineNumberTable size.
 238.268 -     */
 238.269 -    public int getnumlines(){
 238.270 -        return lin_num_tb.size();
 238.271 -    }
 238.272 -
 238.273 -    /**
 238.274 -     * Return LineNumberTable
 238.275 -     */
 238.276 -    public Vector getlin_num_tb(){
 238.277 -        return lin_num_tb;
 238.278 -    }
 238.279 -
 238.280 -    /**
 238.281 -     * Return LocalVariableTable size.
 238.282 -     */
 238.283 -    public int getloc_var_tbsize(){
 238.284 -        return loc_var_tb.size();
 238.285 -    }
 238.286 -
 238.287 -
 238.288 -    /**
 238.289 -     * Return LocalVariableTable.
 238.290 -     */
 238.291 -    public Vector getloc_var_tb(){
 238.292 -        return loc_var_tb;
 238.293 -    }
 238.294 -
 238.295 -    /**
 238.296 -     * Return StackMap.
 238.297 -     */
 238.298 -    public StackMapData[] getStackMap() {
 238.299 -        return stackMap;
 238.300 -    }
 238.301 -
 238.302 -    /**
 238.303 -     * Return StackMapTable.
 238.304 -     */
 238.305 -    public StackMapTableData[] getStackMapTable() {
 238.306 -        return stackMapTable;
 238.307 -    }
 238.308 -
 238.309 -    public StackMapIterator createStackMapIterator() {
 238.310 -        return new StackMapIterator(this);
 238.311 -    }
 238.312 -
 238.313 -    /**
 238.314 -     * Return true if method is static
 238.315 -     */
 238.316 -    public boolean isStatic(){
 238.317 -        if ((access & ACC_STATIC)   !=0) return true;
 238.318 -        return false;
 238.319 -    }
 238.320 -
 238.321 -
 238.322 -    /**
 238.323 -     * Return max depth of operand stack.
 238.324 -     */
 238.325 -    public int getMaxStack(){
 238.326 -        return  max_stack;
 238.327 -    }
 238.328 -
 238.329 -
 238.330 -    /**
 238.331 -     * Return number of local variables.
 238.332 -     */
 238.333 -    public int getMaxLocals(){
 238.334 -        return max_locals;
 238.335 -    }
 238.336 -
 238.337 -
 238.338 -    /**
 238.339 -     * Return exception index table in Exception attribute.
 238.340 -     */
 238.341 -    public int []get_exc_index_table(){
 238.342 -        return  exc_index_table;
 238.343 -    }
 238.344 -
 238.345 -
 238.346 -    /**
 238.347 -     * Return exception table in code attributre.
 238.348 -     */
 238.349 -    public TrapDataIterator getTrapDataIterator(){
 238.350 -        return new TrapDataIterator(exception_table);
 238.351 -    }
 238.352 -    
 238.353 -
 238.354 -    /**
 238.355 -     * Return method attributes.
 238.356 -     */
 238.357 -    public Vector getAttributes(){
 238.358 -        return attrs;
 238.359 -    }
 238.360 -
 238.361 -
 238.362 -    /**
 238.363 -     * Return code attributes.
 238.364 -     */
 238.365 -    public Vector getCodeAttributes(){
 238.366 -        return code_attrs;
 238.367 -    }
 238.368 -
 238.369 -
 238.370 -    /**
 238.371 -     * Return true if method id synthetic.
 238.372 -     */
 238.373 -    public boolean isSynthetic(){
 238.374 -        return isSynthetic;
 238.375 -    }
 238.376 -
 238.377 -
 238.378 -    /**
 238.379 -     * Return true if method is deprecated.
 238.380 -     */
 238.381 -    public boolean isDeprecated(){
 238.382 -        return isDeprecated;
 238.383 -    }
 238.384 -
 238.385 -    public byte[] findAnnotationData(boolean classRetention) {
 238.386 -        String n = classRetention ?
 238.387 -            "RuntimeInvisibleAnnotations" : // NOI18N
 238.388 -            "RuntimeVisibleAnnotations"; // NOI18N
 238.389 -        AttrData[] arr = new AttrData[attrs.size()];
 238.390 -        attrs.copyInto(arr);
 238.391 -        return ClassData.findAttr(n, arr);
 238.392 -    }
 238.393 -
 238.394 -    public boolean isConstructor() {
 238.395 -        return "<init>".equals(getName());
 238.396 -    }
 238.397 -}
   239.1 --- a/rt/javap/src/main/java/org/apidesign/javap/RuntimeConstants.java	Wed Feb 27 17:50:47 2013 +0100
   239.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   239.3 @@ -1,787 +0,0 @@
   239.4 -/*
   239.5 - * Copyright (c) 2002, 2005, Oracle and/or its affiliates. All rights reserved.
   239.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   239.7 - *
   239.8 - * This code is free software; you can redistribute it and/or modify it
   239.9 - * under the terms of the GNU General Public License version 2 only, as
  239.10 - * published by the Free Software Foundation.  Oracle designates this
  239.11 - * particular file as subject to the "Classpath" exception as provided
  239.12 - * by Oracle in the LICENSE file that accompanied this code.
  239.13 - *
  239.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  239.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  239.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  239.17 - * version 2 for more details (a copy is included in the LICENSE file that
  239.18 - * accompanied this code).
  239.19 - *
  239.20 - * You should have received a copy of the GNU General Public License version
  239.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  239.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  239.23 - *
  239.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  239.25 - * or visit www.oracle.com if you need additional information or have any
  239.26 - * questions.
  239.27 - */
  239.28 -
  239.29 -
  239.30 -package org.apidesign.javap;
  239.31 -
  239.32 -public interface RuntimeConstants {
  239.33 -
  239.34 -    /* Signature Characters */
  239.35 -    public static final char   SIGC_VOID                  = 'V';
  239.36 -    public static final String SIG_VOID                   = "V";
  239.37 -    public static final char   SIGC_BOOLEAN               = 'Z';
  239.38 -    public static final String SIG_BOOLEAN                = "Z";
  239.39 -    public static final char   SIGC_BYTE                  = 'B';
  239.40 -    public static final String SIG_BYTE                   = "B";
  239.41 -    public static final char   SIGC_CHAR                  = 'C';
  239.42 -    public static final String SIG_CHAR                   = "C";
  239.43 -    public static final char   SIGC_SHORT                 = 'S';
  239.44 -    public static final String SIG_SHORT                  = "S";
  239.45 -    public static final char   SIGC_INT                   = 'I';
  239.46 -    public static final String SIG_INT                    = "I";
  239.47 -    public static final char   SIGC_LONG                  = 'J';
  239.48 -    public static final String SIG_LONG                   = "J";
  239.49 -    public static final char   SIGC_FLOAT                 = 'F';
  239.50 -    public static final String SIG_FLOAT                  = "F";
  239.51 -    public static final char   SIGC_DOUBLE                = 'D';
  239.52 -    public static final String SIG_DOUBLE                 = "D";
  239.53 -    public static final char   SIGC_ARRAY                 = '[';
  239.54 -    public static final String SIG_ARRAY                  = "[";
  239.55 -    public static final char   SIGC_CLASS                 = 'L';
  239.56 -    public static final String SIG_CLASS                  = "L";
  239.57 -    public static final char   SIGC_METHOD                = '(';
  239.58 -    public static final String SIG_METHOD                 = "(";
  239.59 -    public static final char   SIGC_ENDCLASS              = ';';
  239.60 -    public static final String SIG_ENDCLASS               = ";";
  239.61 -    public static final char   SIGC_ENDMETHOD             = ')';
  239.62 -    public static final String SIG_ENDMETHOD              = ")";
  239.63 -    public static final char   SIGC_PACKAGE               = '/';
  239.64 -    public static final String SIG_PACKAGE                = "/";
  239.65 -
  239.66 -    /* Class File Constants */
  239.67 -    public static final int JAVA_MAGIC                   = 0xcafebabe;
  239.68 -    public static final int JAVA_VERSION                 = 45;
  239.69 -    public static final int JAVA_MINOR_VERSION           = 3;
  239.70 -
  239.71 -    /* Constant table */
  239.72 -    public static final int CONSTANT_UTF8                = 1;
  239.73 -    public static final int CONSTANT_UNICODE             = 2;
  239.74 -    public static final int CONSTANT_INTEGER             = 3;
  239.75 -    public static final int CONSTANT_FLOAT               = 4;
  239.76 -    public static final int CONSTANT_LONG                = 5;
  239.77 -    public static final int CONSTANT_DOUBLE              = 6;
  239.78 -    public static final int CONSTANT_CLASS               = 7;
  239.79 -    public static final int CONSTANT_STRING              = 8;
  239.80 -    public static final int CONSTANT_FIELD               = 9;
  239.81 -    public static final int CONSTANT_METHOD              = 10;
  239.82 -    public static final int CONSTANT_INTERFACEMETHOD     = 11;
  239.83 -    public static final int CONSTANT_NAMEANDTYPE         = 12;
  239.84 -
  239.85 -    /* Access Flags */
  239.86 -    public static final int ACC_PUBLIC                   = 0x00000001;
  239.87 -    public static final int ACC_PRIVATE                  = 0x00000002;
  239.88 -    public static final int ACC_PROTECTED                = 0x00000004;
  239.89 -    public static final int ACC_STATIC                   = 0x00000008;
  239.90 -    public static final int ACC_FINAL                    = 0x00000010;
  239.91 -    public static final int ACC_SYNCHRONIZED             = 0x00000020;
  239.92 -    public static final int ACC_SUPER                        = 0x00000020;
  239.93 -    public static final int ACC_VOLATILE                 = 0x00000040;
  239.94 -    public static final int ACC_TRANSIENT                = 0x00000080;
  239.95 -    public static final int ACC_NATIVE                   = 0x00000100;
  239.96 -    public static final int ACC_INTERFACE                = 0x00000200;
  239.97 -    public static final int ACC_ABSTRACT                 = 0x00000400;
  239.98 -    public static final int ACC_STRICT                   = 0x00000800;
  239.99 -    public static final int ACC_EXPLICIT                 = 0x00001000;
 239.100 -    public static final int ACC_SYNTHETIC                = 0x00010000; // actually, this is an attribute
 239.101 -
 239.102 -    /* Type codes */
 239.103 -    public static final int T_CLASS                      = 0x00000002;
 239.104 -    public static final int T_BOOLEAN                    = 0x00000004;
 239.105 -    public static final int T_CHAR                       = 0x00000005;
 239.106 -    public static final int T_FLOAT                      = 0x00000006;
 239.107 -    public static final int T_DOUBLE                     = 0x00000007;
 239.108 -    public static final int T_BYTE                       = 0x00000008;
 239.109 -    public static final int T_SHORT                      = 0x00000009;
 239.110 -    public static final int T_INT                        = 0x0000000a;
 239.111 -    public static final int T_LONG                       = 0x0000000b;
 239.112 -
 239.113 -    /* Type codes for StackMap attribute */
 239.114 -    public static final int ITEM_Bogus      =0; // an unknown or uninitialized value
 239.115 -    public static final int ITEM_Integer    =1; // a 32-bit integer
 239.116 -    public static final int ITEM_Float      =2; // not used
 239.117 -    public static final int ITEM_Double     =3; // not used
 239.118 -    public static final int ITEM_Long       =4; // a 64-bit integer
 239.119 -    public static final int ITEM_Null       =5; // the type of null
 239.120 -    public static final int ITEM_InitObject =6; // "this" in constructor
 239.121 -    public static final int ITEM_Object     =7; // followed by 2-byte index of class name
 239.122 -    public static final int ITEM_NewObject  =8; // followed by 2-byte ref to "new"
 239.123 -
 239.124 -    /* Constants used in StackMapTable attribute */
 239.125 -    public static final int SAME_FRAME_BOUND                  = 64;
 239.126 -    public static final int SAME_LOCALS_1_STACK_ITEM_BOUND    = 128;
 239.127 -    public static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 239.128 -    public static final int SAME_FRAME_EXTENDED               = 251;
 239.129 -    public static final int FULL_FRAME                        = 255;
 239.130 -
 239.131 -    /* Opcodes */
 239.132 -    public static final int opc_dead                     = -2;
 239.133 -    public static final int opc_label                    = -1;
 239.134 -    public static final int opc_nop                      = 0;
 239.135 -    public static final int opc_aconst_null              = 1;
 239.136 -    public static final int opc_iconst_m1                = 2;
 239.137 -    public static final int opc_iconst_0                 = 3;
 239.138 -    public static final int opc_iconst_1                 = 4;
 239.139 -    public static final int opc_iconst_2                 = 5;
 239.140 -    public static final int opc_iconst_3                 = 6;
 239.141 -    public static final int opc_iconst_4                 = 7;
 239.142 -    public static final int opc_iconst_5                 = 8;
 239.143 -    public static final int opc_lconst_0                 = 9;
 239.144 -    public static final int opc_lconst_1                 = 10;
 239.145 -    public static final int opc_fconst_0                 = 11;
 239.146 -    public static final int opc_fconst_1                 = 12;
 239.147 -    public static final int opc_fconst_2                 = 13;
 239.148 -    public static final int opc_dconst_0                 = 14;
 239.149 -    public static final int opc_dconst_1                 = 15;
 239.150 -    public static final int opc_bipush                   = 16;
 239.151 -    public static final int opc_sipush                   = 17;
 239.152 -    public static final int opc_ldc                      = 18;
 239.153 -    public static final int opc_ldc_w                    = 19;
 239.154 -    public static final int opc_ldc2_w                   = 20;
 239.155 -    public static final int opc_iload                    = 21;
 239.156 -    public static final int opc_lload                    = 22;
 239.157 -    public static final int opc_fload                    = 23;
 239.158 -    public static final int opc_dload                    = 24;
 239.159 -    public static final int opc_aload                    = 25;
 239.160 -    public static final int opc_iload_0                  = 26;
 239.161 -    public static final int opc_iload_1                  = 27;
 239.162 -    public static final int opc_iload_2                  = 28;
 239.163 -    public static final int opc_iload_3                  = 29;
 239.164 -    public static final int opc_lload_0                  = 30;
 239.165 -    public static final int opc_lload_1                  = 31;
 239.166 -    public static final int opc_lload_2                  = 32;
 239.167 -    public static final int opc_lload_3                  = 33;
 239.168 -    public static final int opc_fload_0                  = 34;
 239.169 -    public static final int opc_fload_1                  = 35;
 239.170 -    public static final int opc_fload_2                  = 36;
 239.171 -    public static final int opc_fload_3                  = 37;
 239.172 -    public static final int opc_dload_0                  = 38;
 239.173 -    public static final int opc_dload_1                  = 39;
 239.174 -    public static final int opc_dload_2                  = 40;
 239.175 -    public static final int opc_dload_3                  = 41;
 239.176 -    public static final int opc_aload_0                  = 42;
 239.177 -    public static final int opc_aload_1                  = 43;
 239.178 -    public static final int opc_aload_2                  = 44;
 239.179 -    public static final int opc_aload_3                  = 45;
 239.180 -    public static final int opc_iaload                   = 46;
 239.181 -    public static final int opc_laload                   = 47;
 239.182 -    public static final int opc_faload                   = 48;
 239.183 -    public static final int opc_daload                   = 49;
 239.184 -    public static final int opc_aaload                   = 50;
 239.185 -    public static final int opc_baload                   = 51;
 239.186 -    public static final int opc_caload                   = 52;
 239.187 -    public static final int opc_saload                   = 53;
 239.188 -    public static final int opc_istore                   = 54;
 239.189 -    public static final int opc_lstore                   = 55;
 239.190 -    public static final int opc_fstore                   = 56;
 239.191 -    public static final int opc_dstore                   = 57;
 239.192 -    public static final int opc_astore                   = 58;
 239.193 -    public static final int opc_istore_0                 = 59;
 239.194 -    public static final int opc_istore_1                 = 60;
 239.195 -    public static final int opc_istore_2                 = 61;
 239.196 -    public static final int opc_istore_3                 = 62;
 239.197 -    public static final int opc_lstore_0                 = 63;
 239.198 -    public static final int opc_lstore_1                 = 64;
 239.199 -    public static final int opc_lstore_2                 = 65;
 239.200 -    public static final int opc_lstore_3                 = 66;
 239.201 -    public static final int opc_fstore_0                 = 67;
 239.202 -    public static final int opc_fstore_1                 = 68;
 239.203 -    public static final int opc_fstore_2                 = 69;
 239.204 -    public static final int opc_fstore_3                 = 70;
 239.205 -    public static final int opc_dstore_0                 = 71;
 239.206 -    public static final int opc_dstore_1                 = 72;
 239.207 -    public static final int opc_dstore_2                 = 73;
 239.208 -    public static final int opc_dstore_3                 = 74;
 239.209 -    public static final int opc_astore_0                 = 75;
 239.210 -    public static final int opc_astore_1                 = 76;
 239.211 -    public static final int opc_astore_2                 = 77;
 239.212 -    public static final int opc_astore_3                 = 78;
 239.213 -    public static final int opc_iastore                  = 79;
 239.214 -    public static final int opc_lastore                  = 80;
 239.215 -    public static final int opc_fastore                  = 81;
 239.216 -    public static final int opc_dastore                  = 82;
 239.217 -    public static final int opc_aastore                  = 83;
 239.218 -    public static final int opc_bastore                  = 84;
 239.219 -    public static final int opc_castore                  = 85;
 239.220 -    public static final int opc_sastore                  = 86;
 239.221 -    public static final int opc_pop                      = 87;
 239.222 -    public static final int opc_pop2                     = 88;
 239.223 -    public static final int opc_dup                      = 89;
 239.224 -    public static final int opc_dup_x1                   = 90;
 239.225 -    public static final int opc_dup_x2                   = 91;
 239.226 -    public static final int opc_dup2                     = 92;
 239.227 -    public static final int opc_dup2_x1                  = 93;
 239.228 -    public static final int opc_dup2_x2                  = 94;
 239.229 -    public static final int opc_swap                     = 95;
 239.230 -    public static final int opc_iadd                     = 96;
 239.231 -    public static final int opc_ladd                     = 97;
 239.232 -    public static final int opc_fadd                     = 98;
 239.233 -    public static final int opc_dadd                     = 99;
 239.234 -    public static final int opc_isub                     = 100;
 239.235 -    public static final int opc_lsub                     = 101;
 239.236 -    public static final int opc_fsub                     = 102;
 239.237 -    public static final int opc_dsub                     = 103;
 239.238 -    public static final int opc_imul                     = 104;
 239.239 -    public static final int opc_lmul                     = 105;
 239.240 -    public static final int opc_fmul                     = 106;
 239.241 -    public static final int opc_dmul                     = 107;
 239.242 -    public static final int opc_idiv                     = 108;
 239.243 -    public static final int opc_ldiv                     = 109;
 239.244 -    public static final int opc_fdiv                     = 110;
 239.245 -    public static final int opc_ddiv                     = 111;
 239.246 -    public static final int opc_irem                     = 112;
 239.247 -    public static final int opc_lrem                     = 113;
 239.248 -    public static final int opc_frem                     = 114;
 239.249 -    public static final int opc_drem                     = 115;
 239.250 -    public static final int opc_ineg                     = 116;
 239.251 -    public static final int opc_lneg                     = 117;
 239.252 -    public static final int opc_fneg                     = 118;
 239.253 -    public static final int opc_dneg                     = 119;
 239.254 -    public static final int opc_ishl                     = 120;
 239.255 -    public static final int opc_lshl                     = 121;
 239.256 -    public static final int opc_ishr                     = 122;
 239.257 -    public static final int opc_lshr                     = 123;
 239.258 -    public static final int opc_iushr                    = 124;
 239.259 -    public static final int opc_lushr                    = 125;
 239.260 -    public static final int opc_iand                     = 126;
 239.261 -    public static final int opc_land                     = 127;
 239.262 -    public static final int opc_ior                      = 128;
 239.263 -    public static final int opc_lor                      = 129;
 239.264 -    public static final int opc_ixor                     = 130;
 239.265 -    public static final int opc_lxor                     = 131;
 239.266 -    public static final int opc_iinc                     = 132;
 239.267 -    public static final int opc_i2l                      = 133;
 239.268 -    public static final int opc_i2f                      = 134;
 239.269 -    public static final int opc_i2d                      = 135;
 239.270 -    public static final int opc_l2i                      = 136;
 239.271 -    public static final int opc_l2f                      = 137;
 239.272 -    public static final int opc_l2d                      = 138;
 239.273 -    public static final int opc_f2i                      = 139;
 239.274 -    public static final int opc_f2l                      = 140;
 239.275 -    public static final int opc_f2d                      = 141;
 239.276 -    public static final int opc_d2i                      = 142;
 239.277 -    public static final int opc_d2l                      = 143;
 239.278 -    public static final int opc_d2f                      = 144;
 239.279 -    public static final int opc_i2b                      = 145;
 239.280 -    public static final int opc_int2byte                 = 145;
 239.281 -    public static final int opc_i2c                      = 146;
 239.282 -    public static final int opc_int2char                 = 146;
 239.283 -    public static final int opc_i2s                      = 147;
 239.284 -    public static final int opc_int2short                = 147;
 239.285 -    public static final int opc_lcmp                     = 148;
 239.286 -    public static final int opc_fcmpl                    = 149;
 239.287 -    public static final int opc_fcmpg                    = 150;
 239.288 -    public static final int opc_dcmpl                    = 151;
 239.289 -    public static final int opc_dcmpg                    = 152;
 239.290 -    public static final int opc_ifeq                     = 153;
 239.291 -    public static final int opc_ifne                     = 154;
 239.292 -    public static final int opc_iflt                     = 155;
 239.293 -    public static final int opc_ifge                     = 156;
 239.294 -    public static final int opc_ifgt                     = 157;
 239.295 -    public static final int opc_ifle                     = 158;
 239.296 -    public static final int opc_if_icmpeq                = 159;
 239.297 -    public static final int opc_if_icmpne                = 160;
 239.298 -    public static final int opc_if_icmplt                = 161;
 239.299 -    public static final int opc_if_icmpge                = 162;
 239.300 -    public static final int opc_if_icmpgt                = 163;
 239.301 -    public static final int opc_if_icmple                = 164;
 239.302 -    public static final int opc_if_acmpeq                = 165;
 239.303 -    public static final int opc_if_acmpne                = 166;
 239.304 -    public static final int opc_goto                     = 167;
 239.305 -    public static final int opc_jsr                      = 168;
 239.306 -    public static final int opc_ret                      = 169;
 239.307 -    public static final int opc_tableswitch              = 170;
 239.308 -    public static final int opc_lookupswitch             = 171;
 239.309 -    public static final int opc_ireturn                  = 172;
 239.310 -    public static final int opc_lreturn                  = 173;
 239.311 -    public static final int opc_freturn                  = 174;
 239.312 -    public static final int opc_dreturn                  = 175;
 239.313 -    public static final int opc_areturn                  = 176;
 239.314 -    public static final int opc_return                   = 177;
 239.315 -    public static final int opc_getstatic                = 178;
 239.316 -    public static final int opc_putstatic                = 179;
 239.317 -    public static final int opc_getfield                 = 180;
 239.318 -    public static final int opc_putfield                 = 181;
 239.319 -    public static final int opc_invokevirtual            = 182;
 239.320 -    public static final int opc_invokenonvirtual         = 183;
 239.321 -    public static final int opc_invokespecial            = 183;
 239.322 -    public static final int opc_invokestatic             = 184;
 239.323 -    public static final int opc_invokeinterface          = 185;
 239.324 -//    public static final int opc_xxxunusedxxx             = 186;
 239.325 -    public static final int opc_new                      = 187;
 239.326 -    public static final int opc_newarray                 = 188;
 239.327 -    public static final int opc_anewarray                = 189;
 239.328 -    public static final int opc_arraylength              = 190;
 239.329 -    public static final int opc_athrow                   = 191;
 239.330 -    public static final int opc_checkcast                = 192;
 239.331 -    public static final int opc_instanceof               = 193;
 239.332 -    public static final int opc_monitorenter             = 194;
 239.333 -    public static final int opc_monitorexit              = 195;
 239.334 -    public static final int opc_wide                     = 196;
 239.335 -    public static final int opc_multianewarray           = 197;
 239.336 -    public static final int opc_ifnull                   = 198;
 239.337 -    public static final int opc_ifnonnull                = 199;
 239.338 -    public static final int opc_goto_w                   = 200;
 239.339 -    public static final int opc_jsr_w                    = 201;
 239.340 -        /* Pseudo-instructions */
 239.341 -    public static final int opc_bytecode                 = 203;
 239.342 -    public static final int opc_try                      = 204;
 239.343 -    public static final int opc_endtry                   = 205;
 239.344 -    public static final int opc_catch                    = 206;
 239.345 -    public static final int opc_var                      = 207;
 239.346 -    public static final int opc_endvar                   = 208;
 239.347 -    public static final int opc_localsmap                = 209;
 239.348 -    public static final int opc_stackmap                 = 210;
 239.349 -        /* PicoJava prefixes */
 239.350 -    public static final int opc_nonpriv                  = 254;
 239.351 -    public static final int opc_priv                     = 255;
 239.352 -
 239.353 -        /* Wide instructions */
 239.354 -    public static final int opc_iload_w         = (opc_wide<<8)|opc_iload;
 239.355 -    public static final int opc_lload_w         = (opc_wide<<8)|opc_lload;
 239.356 -    public static final int opc_fload_w         = (opc_wide<<8)|opc_fload;
 239.357 -    public static final int opc_dload_w         = (opc_wide<<8)|opc_dload;
 239.358 -    public static final int opc_aload_w         = (opc_wide<<8)|opc_aload;
 239.359 -    public static final int opc_istore_w        = (opc_wide<<8)|opc_istore;
 239.360 -    public static final int opc_lstore_w        = (opc_wide<<8)|opc_lstore;
 239.361 -    public static final int opc_fstore_w        = (opc_wide<<8)|opc_fstore;
 239.362 -    public static final int opc_dstore_w        = (opc_wide<<8)|opc_dstore;
 239.363 -    public static final int opc_astore_w        = (opc_wide<<8)|opc_astore;
 239.364 -    public static final int opc_ret_w           = (opc_wide<<8)|opc_ret;
 239.365 -    public static final int opc_iinc_w          = (opc_wide<<8)|opc_iinc;
 239.366 -
 239.367 -    /* Opcode Names */
 239.368 -  public static final String opcNamesTab[] = {
 239.369 -        "nop",
 239.370 -        "aconst_null",
 239.371 -        "iconst_m1",
 239.372 -        "iconst_0",
 239.373 -        "iconst_1",
 239.374 -        "iconst_2",
 239.375 -        "iconst_3",
 239.376 -        "iconst_4",
 239.377 -        "iconst_5",
 239.378 -        "lconst_0",
 239.379 -        "lconst_1",
 239.380 -        "fconst_0",
 239.381 -        "fconst_1",
 239.382 -        "fconst_2",
 239.383 -        "dconst_0",
 239.384 -        "dconst_1",
 239.385 -        "bipush",
 239.386 -        "sipush",
 239.387 -        "ldc",
 239.388 -        "ldc_w",
 239.389 -        "ldc2_w",
 239.390 -        "iload",
 239.391 -        "lload",
 239.392 -        "fload",
 239.393 -        "dload",
 239.394 -        "aload",
 239.395 -        "iload_0",
 239.396 -        "iload_1",
 239.397 -        "iload_2",
 239.398 -        "iload_3",
 239.399 -        "lload_0",
 239.400 -        "lload_1",
 239.401 -        "lload_2",
 239.402 -        "lload_3",
 239.403 -        "fload_0",
 239.404 -        "fload_1",
 239.405 -        "fload_2",
 239.406 -        "fload_3",
 239.407 -        "dload_0",
 239.408 -        "dload_1",
 239.409 -        "dload_2",
 239.410 -        "dload_3",
 239.411 -        "aload_0",
 239.412 -        "aload_1",
 239.413 -        "aload_2",
 239.414 -        "aload_3",
 239.415 -        "iaload",
 239.416 -        "laload",
 239.417 -        "faload",
 239.418 -        "daload",
 239.419 -        "aaload",
 239.420 -        "baload",
 239.421 -        "caload",
 239.422 -        "saload",
 239.423 -        "istore",
 239.424 -        "lstore",
 239.425 -        "fstore",
 239.426 -        "dstore",
 239.427 -        "astore",
 239.428 -        "istore_0",
 239.429 -        "istore_1",
 239.430 -        "istore_2",
 239.431 -        "istore_3",
 239.432 -        "lstore_0",
 239.433 -        "lstore_1",
 239.434 -        "lstore_2",
 239.435 -        "lstore_3",
 239.436 -        "fstore_0",
 239.437 -        "fstore_1",
 239.438 -        "fstore_2",
 239.439 -        "fstore_3",
 239.440 -        "dstore_0",
 239.441 -        "dstore_1",
 239.442 -        "dstore_2",
 239.443 -        "dstore_3",
 239.444 -        "astore_0",
 239.445 -        "astore_1",
 239.446 -        "astore_2",
 239.447 -        "astore_3",
 239.448 -        "iastore",
 239.449 -        "lastore",
 239.450 -        "fastore",
 239.451 -        "dastore",
 239.452 -        "aastore",
 239.453 -        "bastore",
 239.454 -        "castore",
 239.455 -        "sastore",
 239.456 -        "pop",
 239.457 -        "pop2",
 239.458 -        "dup",
 239.459 -        "dup_x1",
 239.460 -        "dup_x2",
 239.461 -        "dup2",
 239.462 -        "dup2_x1",
 239.463 -        "dup2_x2",
 239.464 -        "swap",
 239.465 -        "iadd",
 239.466 -        "ladd",
 239.467 -        "fadd",
 239.468 -        "dadd",
 239.469 -        "isub",
 239.470 -        "lsub",
 239.471 -        "fsub",
 239.472 -        "dsub",
 239.473 -        "imul",
 239.474 -        "lmul",
 239.475 -        "fmul",
 239.476 -        "dmul",
 239.477 -        "idiv",
 239.478 -        "ldiv",
 239.479 -        "fdiv",
 239.480 -        "ddiv",
 239.481 -        "irem",
 239.482 -        "lrem",
 239.483 -        "frem",
 239.484 -        "drem",
 239.485 -        "ineg",
 239.486 -        "lneg",
 239.487 -        "fneg",
 239.488 -        "dneg",
 239.489 -        "ishl",
 239.490 -        "lshl",
 239.491 -        "ishr",
 239.492 -        "lshr",
 239.493 -        "iushr",
 239.494 -        "lushr",
 239.495 -        "iand",
 239.496 -        "land",
 239.497 -        "ior",
 239.498 -        "lor",
 239.499 -        "ixor",
 239.500 -        "lxor",
 239.501 -        "iinc",
 239.502 -        "i2l",
 239.503 -        "i2f",
 239.504 -        "i2d",
 239.505 -        "l2i",
 239.506 -        "l2f",
 239.507 -        "l2d",
 239.508 -        "f2i",
 239.509 -        "f2l",
 239.510 -        "f2d",
 239.511 -        "d2i",
 239.512 -        "d2l",
 239.513 -        "d2f",
 239.514 -        "i2b",
 239.515 -        "i2c",
 239.516 -        "i2s",
 239.517 -        "lcmp",
 239.518 -        "fcmpl",
 239.519 -        "fcmpg",
 239.520 -        "dcmpl",
 239.521 -        "dcmpg",
 239.522 -        "ifeq",
 239.523 -        "ifne",
 239.524 -        "iflt",
 239.525 -        "ifge",
 239.526 -        "ifgt",
 239.527 -        "ifle",
 239.528 -        "if_icmpeq",
 239.529 -        "if_icmpne",
 239.530 -        "if_icmplt",
 239.531 -        "if_icmpge",
 239.532 -        "if_icmpgt",
 239.533 -        "if_icmple",
 239.534 -        "if_acmpeq",
 239.535 -        "if_acmpne",
 239.536 -        "goto",
 239.537 -        "jsr",
 239.538 -        "ret",
 239.539 -        "tableswitch",
 239.540 -        "lookupswitch",
 239.541 -        "ireturn",
 239.542 -        "lreturn",
 239.543 -        "freturn",
 239.544 -        "dreturn",
 239.545 -        "areturn",
 239.546 -        "return",
 239.547 -        "getstatic",
 239.548 -        "putstatic",
 239.549 -        "getfield",
 239.550 -        "putfield",
 239.551 -        "invokevirtual",
 239.552 -        "invokespecial", //     was "invokenonvirtual",
 239.553 -        "invokestatic",
 239.554 -        "invokeinterface",
 239.555 -        "bytecode 186", //"xxxunusedxxx",
 239.556 -        "new",
 239.557 -        "newarray",
 239.558 -        "anewarray",
 239.559 -        "arraylength",
 239.560 -        "athrow",
 239.561 -        "checkcast",
 239.562 -        "instanceof",
 239.563 -        "monitorenter",
 239.564 -        "monitorexit",
 239.565 -         null, // "wide",
 239.566 -        "multianewarray",
 239.567 -        "ifnull",
 239.568 -        "ifnonnull",
 239.569 -        "goto_w",
 239.570 -        "jsr_w",
 239.571 -        "bytecode 202", // "breakpoint",
 239.572 -        "bytecode",
 239.573 -        "try",
 239.574 -        "endtry",
 239.575 -        "catch",
 239.576 -        "var",
 239.577 -        "endvar",
 239.578 -        "locals_map",
 239.579 -        "stack_map"
 239.580 -  };
 239.581 -
 239.582 -    /* Opcode Lengths */
 239.583 -  public static final int opcLengthsTab[] = {
 239.584 -        1,
 239.585 -        1,
 239.586 -        1,
 239.587 -        1,
 239.588 -        1,
 239.589 -        1,
 239.590 -        1,
 239.591 -        1,
 239.592 -        1,
 239.593 -        1,
 239.594 -        1,
 239.595 -        1,
 239.596 -        1,
 239.597 -        1,
 239.598 -        1,
 239.599 -        1,
 239.600 -        2,
 239.601 -        3,
 239.602 -        2,
 239.603 -        3,
 239.604 -        3,
 239.605 -        2,
 239.606 -        2,
 239.607 -        2,
 239.608 -        2,
 239.609 -        2,
 239.610 -        1,
 239.611 -        1,
 239.612 -        1,
 239.613 -        1,
 239.614 -        1,
 239.615 -        1,
 239.616 -        1,
 239.617 -        1,
 239.618 -        1,
 239.619 -        1,
 239.620 -        1,
 239.621 -        1,
 239.622 -        1,
 239.623 -        1,
 239.624 -        1,
 239.625 -        1,
 239.626 -        1,
 239.627 -        1,
 239.628 -        1,
 239.629 -        1,
 239.630 -        1,
 239.631 -        1,
 239.632 -        1,
 239.633 -        1,
 239.634 -        1,
 239.635 -        1,
 239.636 -        1,
 239.637 -        1,
 239.638 -        2,
 239.639 -        2,
 239.640 -        2,
 239.641 -        2,
 239.642 -        2,
 239.643 -        1,
 239.644 -        1,
 239.645 -        1,
 239.646 -        1,
 239.647 -        1,
 239.648 -        1,
 239.649 -        1,
 239.650 -        1,
 239.651 -        1,
 239.652 -        1,
 239.653 -        1,
 239.654 -        1,
 239.655 -        1,
 239.656 -        1,
 239.657 -        1,
 239.658 -        1,
 239.659 -        1,
 239.660 -        1,
 239.661 -        1,
 239.662 -        1,
 239.663 -        1,
 239.664 -        1,
 239.665 -        1,
 239.666 -        1,
 239.667 -        1,
 239.668 -        1,
 239.669 -        1,
 239.670 -        1,
 239.671 -        1,
 239.672 -        1,
 239.673 -        1,
 239.674 -        1,
 239.675 -        1,
 239.676 -        1,
 239.677 -        1,
 239.678 -        1,
 239.679 -        1,
 239.680 -        1,
 239.681 -        1,
 239.682 -        1,
 239.683 -        1,
 239.684 -        1,
 239.685 -        1,
 239.686 -        1,
 239.687 -        1,
 239.688 -        1,
 239.689 -        1,
 239.690 -        1,
 239.691 -        1,
 239.692 -        1,
 239.693 -        1,
 239.694 -        1,
 239.695 -        1,
 239.696 -        1,
 239.697 -        1,
 239.698 -        1,
 239.699 -        1,
 239.700 -        1,
 239.701 -        1,
 239.702 -        1,
 239.703 -        1,
 239.704 -        1,
 239.705 -        1,
 239.706 -        1,
 239.707 -        1,
 239.708 -        1,
 239.709 -        1,
 239.710 -        1,
 239.711 -        1,
 239.712 -        1,
 239.713 -        1,
 239.714 -        1,
 239.715 -        1,
 239.716 -        3,
 239.717 -        1,
 239.718 -        1,
 239.719 -        1,
 239.720 -        1,
 239.721 -        1,
 239.722 -        1,
 239.723 -        1,
 239.724 -        1,
 239.725 -        1,
 239.726 -        1,
 239.727 -        1,
 239.728 -        1,
 239.729 -        1,
 239.730 -        1,
 239.731 -        1,
 239.732 -        1,
 239.733 -        1,
 239.734 -        1,
 239.735 -        1,
 239.736 -        1,
 239.737 -        3,
 239.738 -        3,
 239.739 -        3,
 239.740 -        3,
 239.741 -        3,
 239.742 -        3,
 239.743 -        3,
 239.744 -        3,
 239.745 -        3,
 239.746 -        3,
 239.747 -        3,
 239.748 -        3,
 239.749 -        3,
 239.750 -        3,
 239.751 -        3,
 239.752 -        3,
 239.753 -        2,
 239.754 -        99,
 239.755 -        99,
 239.756 -        1,
 239.757 -        1,
 239.758 -        1,
 239.759 -        1,
 239.760 -        1,
 239.761 -        1,
 239.762 -        3,
 239.763 -        3,
 239.764 -        3,
 239.765 -        3,
 239.766 -        3,
 239.767 -        3,
 239.768 -        3,
 239.769 -        5,
 239.770 -        0,
 239.771 -        3,
 239.772 -        2,
 239.773 -        3,
 239.774 -        1,
 239.775 -        1,
 239.776 -        3,
 239.777 -        3,
 239.778 -        1,
 239.779 -        1,
 239.780 -        0, // wide
 239.781 -        4,
 239.782 -        3,
 239.783 -        3,
 239.784 -        5,
 239.785 -        5,
 239.786 -        1,
 239.787 -        1, 0, 0, 0, 0, 0 // pseudo
 239.788 -  };
 239.789 -
 239.790 -}
   240.1 --- a/rt/javap/src/main/java/org/apidesign/javap/StackMapData.java	Wed Feb 27 17:50:47 2013 +0100
   240.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   240.3 @@ -1,71 +0,0 @@
   240.4 -/*
   240.5 - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
   240.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   240.7 - *
   240.8 - * This code is free software; you can redistribute it and/or modify it
   240.9 - * under the terms of the GNU General Public License version 2 only, as
  240.10 - * published by the Free Software Foundation.  Oracle designates this
  240.11 - * particular file as subject to the "Classpath" exception as provided
  240.12 - * by Oracle in the LICENSE file that accompanied this code.
  240.13 - *
  240.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  240.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  240.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  240.17 - * version 2 for more details (a copy is included in the LICENSE file that
  240.18 - * accompanied this code).
  240.19 - *
  240.20 - * You should have received a copy of the GNU General Public License version
  240.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  240.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  240.23 - *
  240.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  240.25 - * or visit www.oracle.com if you need additional information or have any
  240.26 - * questions.
  240.27 - */
  240.28 -
  240.29 -
  240.30 -package org.apidesign.javap;
  240.31 -
  240.32 -import java.util.*;
  240.33 -import java.io.*;
  240.34 -
  240.35 -import static org.apidesign.javap.RuntimeConstants.*;
  240.36 -
  240.37 -/* represents one entry of StackMap attribute
  240.38 - */
  240.39 -class StackMapData {
  240.40 -    final int offset;
  240.41 -    final int[] locals;
  240.42 -    final int[] stack;
  240.43 -
  240.44 -    StackMapData(int offset, int[] locals, int[] stack) {
  240.45 -        this.offset = offset;
  240.46 -        this.locals = locals;
  240.47 -        this.stack = stack;
  240.48 -    }
  240.49 -
  240.50 -    StackMapData(DataInputStream in, MethodData method) throws IOException {
  240.51 -        offset = in.readUnsignedShort();
  240.52 -        int local_size = in.readUnsignedShort();
  240.53 -        locals = readTypeArray(in, local_size, method);
  240.54 -        int stack_size = in.readUnsignedShort();
  240.55 -        stack = readTypeArray(in, stack_size, method);
  240.56 -    }
  240.57 -
  240.58 -    static final int[] readTypeArray(DataInputStream in, int length, MethodData method) throws IOException {
  240.59 -        int[] types = new int[length];
  240.60 -        for (int i=0; i<length; i++) {
  240.61 -            types[i] = readType(in, method);
  240.62 -        }
  240.63 -        return types;
  240.64 -    }
  240.65 -
  240.66 -    static final int readType(DataInputStream in, MethodData method) throws IOException {
  240.67 -        int type = in.readUnsignedByte();
  240.68 -        if (type == ITEM_Object || type == ITEM_NewObject) {
  240.69 -            type = type | (in.readUnsignedShort()<<8);
  240.70 -        }
  240.71 -        return type;
  240.72 -    }
  240.73 -
  240.74 -}
   241.1 --- a/rt/javap/src/main/java/org/apidesign/javap/StackMapIterator.java	Wed Feb 27 17:50:47 2013 +0100
   241.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   241.3 @@ -1,179 +0,0 @@
   241.4 -/*
   241.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   241.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   241.7 - *
   241.8 - * This code is free software; you can redistribute it and/or modify it
   241.9 - * under the terms of the GNU General Public License version 2 only, as
  241.10 - * published by the Free Software Foundation.  Oracle designates this
  241.11 - * particular file as subject to the "Classpath" exception as provided
  241.12 - * by Oracle in the LICENSE file that accompanied this code.
  241.13 - *
  241.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  241.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  241.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  241.17 - * version 2 for more details (a copy is included in the LICENSE file that
  241.18 - * accompanied this code).
  241.19 - *
  241.20 - * You should have received a copy of the GNU General Public License version
  241.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  241.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  241.23 - *
  241.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  241.25 - * or visit www.oracle.com if you need additional information or have any
  241.26 - * questions.
  241.27 - */
  241.28 -
  241.29 -package org.apidesign.javap;
  241.30 -
  241.31 -import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
  241.32 -import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
  241.33 -import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
  241.34 -import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
  241.35 -import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
  241.36 -
  241.37 -public final class StackMapIterator {
  241.38 -    private final StackMapTableData[] stackMapTable;
  241.39 -    private final TypeArray argTypes;
  241.40 -    private final TypeArray localTypes;
  241.41 -    private final TypeArray stackTypes;
  241.42 -
  241.43 -    private int nextFrameIndex;
  241.44 -    private int lastFrameByteCodeOffset;
  241.45 -
  241.46 -    private int byteCodeOffset;
  241.47 -
  241.48 -    StackMapIterator(final MethodData methodData) {
  241.49 -        this(methodData.getStackMapTable(),
  241.50 -             methodData.getInternalSig(),
  241.51 -             methodData.isStatic());
  241.52 -    }
  241.53 -
  241.54 -    StackMapIterator(final StackMapTableData[] stackMapTable,
  241.55 -                     final String methodSignature,
  241.56 -                     final boolean isStaticMethod) {
  241.57 -        this.stackMapTable = (stackMapTable != null)
  241.58 -                                 ? stackMapTable
  241.59 -                                 : new StackMapTableData[0];
  241.60 -
  241.61 -        argTypes = getArgTypes(methodSignature, isStaticMethod);
  241.62 -        localTypes = new TypeArray();
  241.63 -        stackTypes = new TypeArray();
  241.64 -
  241.65 -        localTypes.addAll(argTypes);
  241.66 -
  241.67 -        lastFrameByteCodeOffset = -1;
  241.68 -        advanceBy(0);
  241.69 -    }
  241.70 -
  241.71 -    public String getFrameAsString() {
  241.72 -        return (nextFrameIndex == 0)
  241.73 -                   ? StackMapTableData.toString("INITIAL", 0, null, null)
  241.74 -                   : stackMapTable[nextFrameIndex - 1].toString();
  241.75 -    }
  241.76 -
  241.77 -    public int getFrameIndex() {
  241.78 -        return nextFrameIndex;
  241.79 -    }
  241.80 -
  241.81 -    public TypeArray getFrameStack() {
  241.82 -        return stackTypes;
  241.83 -    }
  241.84 -
  241.85 -    public TypeArray getFrameLocals() {
  241.86 -        return localTypes;
  241.87 -    }
  241.88 -
  241.89 -    public TypeArray getArguments() {
  241.90 -        return argTypes;
  241.91 -    }
  241.92 -
  241.93 -    public void advanceBy(final int numByteCodes) {
  241.94 -        if (numByteCodes < 0) {
  241.95 -            throw new IllegalStateException("Forward only iterator");
  241.96 -        }
  241.97 -
  241.98 -        byteCodeOffset += numByteCodes;
  241.99 -        while ((nextFrameIndex < stackMapTable.length)
 241.100 -                    && ((byteCodeOffset - lastFrameByteCodeOffset)
 241.101 -                            >= (stackMapTable[nextFrameIndex].offsetDelta
 241.102 -                                    + 1))) {
 241.103 -            final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
 241.104 -
 241.105 -            lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
 241.106 -            nextFrame.applyTo(localTypes, stackTypes);
 241.107 -
 241.108 -            ++nextFrameIndex;
 241.109 -        }
 241.110 -    }
 241.111 -
 241.112 -    public void advanceTo(final int nextByteCodeOffset) {
 241.113 -        advanceBy(nextByteCodeOffset - byteCodeOffset);
 241.114 -    }
 241.115 -
 241.116 -    private static TypeArray getArgTypes(final String methodSignature,
 241.117 -                                         final boolean isStaticMethod) {
 241.118 -        final TypeArray argTypes = new TypeArray();
 241.119 -
 241.120 -        if (!isStaticMethod) {
 241.121 -            argTypes.add(ITEM_Object);
 241.122 -        }
 241.123 -
 241.124 -        if (methodSignature.charAt(0) != '(') {
 241.125 -            throw new IllegalArgumentException("Invalid method signature");
 241.126 -        }
 241.127 -
 241.128 -        final int length = methodSignature.length();
 241.129 -        boolean skipType = false;
 241.130 -        int argType;
 241.131 -        for (int i = 1; i < length; ++i) {
 241.132 -            switch (methodSignature.charAt(i)) {
 241.133 -                case 'B':
 241.134 -                case 'C':
 241.135 -                case 'S':
 241.136 -                case 'Z':
 241.137 -                case 'I':
 241.138 -                    argType = ITEM_Integer;
 241.139 -                    break;
 241.140 -                case 'J':
 241.141 -                    argType = ITEM_Long;
 241.142 -                    break;
 241.143 -                case 'F':
 241.144 -                    argType = ITEM_Float;
 241.145 -                    break;
 241.146 -                case 'D':
 241.147 -                    argType = ITEM_Double;
 241.148 -                    break;
 241.149 -                case 'L': {
 241.150 -                    i = methodSignature.indexOf(';', i + 1);
 241.151 -                    if (i == -1) {
 241.152 -                        throw new IllegalArgumentException(
 241.153 -                                      "Invalid method signature");
 241.154 -                    }
 241.155 -                    argType = ITEM_Object;
 241.156 -                    break;
 241.157 -                }
 241.158 -                case ')':
 241.159 -                    // not interested in the return value type
 241.160 -                    return argTypes;
 241.161 -                case '[':
 241.162 -                    if (!skipType) {
 241.163 -                        argTypes.add(ITEM_Object);
 241.164 -                        skipType = true;
 241.165 -                    }
 241.166 -                    continue;
 241.167 -
 241.168 -                default:
 241.169 -                    throw new IllegalArgumentException(
 241.170 -                                  "Invalid method signature");
 241.171 -            }
 241.172 -
 241.173 -            if (!skipType) {
 241.174 -                argTypes.add(argType);
 241.175 -            } else {
 241.176 -                skipType = false;
 241.177 -            }
 241.178 -        }
 241.179 -
 241.180 -        return argTypes;
 241.181 -    }
 241.182 -}
   242.1 --- a/rt/javap/src/main/java/org/apidesign/javap/StackMapTableData.java	Wed Feb 27 17:50:47 2013 +0100
   242.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   242.3 @@ -1,223 +0,0 @@
   242.4 -/*
   242.5 - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved.
   242.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   242.7 - *
   242.8 - * This code is free software; you can redistribute it and/or modify it
   242.9 - * under the terms of the GNU General Public License version 2 only, as
  242.10 - * published by the Free Software Foundation.  Oracle designates this
  242.11 - * particular file as subject to the "Classpath" exception as provided
  242.12 - * by Oracle in the LICENSE file that accompanied this code.
  242.13 - *
  242.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  242.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  242.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  242.17 - * version 2 for more details (a copy is included in the LICENSE file that
  242.18 - * accompanied this code).
  242.19 - *
  242.20 - * You should have received a copy of the GNU General Public License version
  242.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  242.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  242.23 - *
  242.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  242.25 - * or visit www.oracle.com if you need additional information or have any
  242.26 - * questions.
  242.27 - */
  242.28 -
  242.29 -
  242.30 -package org.apidesign.javap;
  242.31 -
  242.32 -import java.io.*;
  242.33 -
  242.34 -import static org.apidesign.javap.RuntimeConstants.*;
  242.35 -
  242.36 -/* represents one entry of StackMapTable attribute
  242.37 - */
  242.38 -abstract class StackMapTableData {
  242.39 -    final int frameType;
  242.40 -    int offsetDelta;
  242.41 -
  242.42 -    StackMapTableData(int frameType) {
  242.43 -        this.frameType = frameType;
  242.44 -    }
  242.45 -
  242.46 -    abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
  242.47 -
  242.48 -    protected static String toString(
  242.49 -            final String frameType,
  242.50 -            final int offset,
  242.51 -            final int[] localTypes,
  242.52 -            final int[] stackTypes) {
  242.53 -        final StringBuilder sb = new StringBuilder(frameType);
  242.54 -
  242.55 -        sb.append("(off: +").append(offset);
  242.56 -        if (localTypes != null) {
  242.57 -            sb.append(", locals: ");
  242.58 -            appendTypes(sb, localTypes);
  242.59 -        }
  242.60 -        if (stackTypes != null) {
  242.61 -            sb.append(", stack: ");
  242.62 -            appendTypes(sb, stackTypes);
  242.63 -        }
  242.64 -        sb.append(')');
  242.65 -
  242.66 -        return sb.toString();
  242.67 -    }
  242.68 -
  242.69 -    private static void appendTypes(final StringBuilder sb, final int[] types) {
  242.70 -        sb.append('[');
  242.71 -        if (types.length > 0) {
  242.72 -            sb.append(TypeArray.typeString(types[0]));
  242.73 -            for (int i = 1; i < types.length; ++i) {
  242.74 -                sb.append(", ");
  242.75 -                sb.append(TypeArray.typeString(types[i]));
  242.76 -            }
  242.77 -        }
  242.78 -        sb.append(']');
  242.79 -    }
  242.80 -
  242.81 -    static class SameFrame extends StackMapTableData {
  242.82 -        SameFrame(int frameType, int offsetDelta) {
  242.83 -            super(frameType);
  242.84 -            this.offsetDelta = offsetDelta;
  242.85 -        }
  242.86 -
  242.87 -        @Override
  242.88 -        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
  242.89 -            stackTypes.clear();
  242.90 -        }
  242.91 -
  242.92 -        @Override
  242.93 -        public String toString() {
  242.94 -            return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
  242.95 -                                          ? "_FRAME_EXTENDED" : ""),
  242.96 -                            offsetDelta,
  242.97 -                            null, null);
  242.98 -        }
  242.99 -    }
 242.100 -
 242.101 -    static class SameLocals1StackItem extends StackMapTableData {
 242.102 -        final int[] stack;
 242.103 -        SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
 242.104 -            super(frameType);
 242.105 -            this.offsetDelta = offsetDelta;
 242.106 -            this.stack = stack;
 242.107 -        }
 242.108 -
 242.109 -        @Override
 242.110 -        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
 242.111 -            stackTypes.setAll(stack);
 242.112 -        }
 242.113 -
 242.114 -        @Override
 242.115 -        public String toString() {
 242.116 -            return toString(
 242.117 -                       "SAME_LOCALS_1_STACK_ITEM"
 242.118 -                           + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
 242.119 -                                  ? "_EXTENDED" : ""),
 242.120 -                       offsetDelta,
 242.121 -                       null, stack);
 242.122 -        }
 242.123 -    }
 242.124 -
 242.125 -    static class ChopFrame extends StackMapTableData {
 242.126 -        ChopFrame(int frameType, int offsetDelta) {
 242.127 -            super(frameType);
 242.128 -            this.offsetDelta = offsetDelta;
 242.129 -        }
 242.130 -
 242.131 -        @Override
 242.132 -        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
 242.133 -            localTypes.setSize(localTypes.getSize()
 242.134 -                                   - (SAME_FRAME_EXTENDED - frameType));
 242.135 -            stackTypes.clear();
 242.136 -        }
 242.137 -
 242.138 -        @Override
 242.139 -        public String toString() {
 242.140 -            return toString("CHOP", offsetDelta, null, null);
 242.141 -        }
 242.142 -    }
 242.143 -
 242.144 -    static class AppendFrame extends StackMapTableData {
 242.145 -        final int[] locals;
 242.146 -        AppendFrame(int frameType, int offsetDelta, int[] locals) {
 242.147 -            super(frameType);
 242.148 -            this.offsetDelta = offsetDelta;
 242.149 -            this.locals = locals;
 242.150 -        }
 242.151 -
 242.152 -        @Override
 242.153 -        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
 242.154 -            localTypes.addAll(locals);
 242.155 -            stackTypes.clear();
 242.156 -        }
 242.157 -
 242.158 -        @Override
 242.159 -        public String toString() {
 242.160 -            return toString("APPEND", offsetDelta, locals, null);
 242.161 -        }
 242.162 -    }
 242.163 -
 242.164 -    static class FullFrame extends StackMapTableData {
 242.165 -        final int[] locals;
 242.166 -        final int[] stack;
 242.167 -        FullFrame(int offsetDelta, int[] locals, int[] stack) {
 242.168 -            super(FULL_FRAME);
 242.169 -            this.offsetDelta = offsetDelta;
 242.170 -            this.locals = locals;
 242.171 -            this.stack = stack;
 242.172 -        }
 242.173 -
 242.174 -        @Override
 242.175 -        void applyTo(TypeArray localTypes, TypeArray stackTypes) {
 242.176 -            localTypes.setAll(locals);
 242.177 -            stackTypes.setAll(stack);
 242.178 -        }
 242.179 -
 242.180 -        @Override
 242.181 -        public String toString() {
 242.182 -            return toString("FULL", offsetDelta, locals, stack);
 242.183 -        }
 242.184 -    }
 242.185 -
 242.186 -    static StackMapTableData getInstance(DataInputStream in, MethodData method)
 242.187 -                  throws IOException {
 242.188 -        int frameType = in.readUnsignedByte();
 242.189 -
 242.190 -        if (frameType < SAME_FRAME_BOUND) {
 242.191 -            // same_frame
 242.192 -            return new SameFrame(frameType, frameType);
 242.193 -        } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
 242.194 -            // same_locals_1_stack_item_frame
 242.195 -            // read additional single stack element
 242.196 -            return new SameLocals1StackItem(frameType,
 242.197 -                                            (frameType - SAME_FRAME_BOUND),
 242.198 -                                            StackMapData.readTypeArray(in, 1, method));
 242.199 -        } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
 242.200 -            // same_locals_1_stack_item_extended
 242.201 -            return new SameLocals1StackItem(frameType,
 242.202 -                                            in.readUnsignedShort(),
 242.203 -                                            StackMapData.readTypeArray(in, 1, method));
 242.204 -        } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType  && frameType < SAME_FRAME_EXTENDED) {
 242.205 -            // chop_frame or same_frame_extended
 242.206 -            return new ChopFrame(frameType, in.readUnsignedShort());
 242.207 -        } else if (frameType == SAME_FRAME_EXTENDED) {
 242.208 -            // chop_frame or same_frame_extended
 242.209 -            return new SameFrame(frameType, in.readUnsignedShort());
 242.210 -        } else if (SAME_FRAME_EXTENDED < frameType  && frameType < FULL_FRAME) {
 242.211 -            // append_frame
 242.212 -            return new AppendFrame(frameType, in.readUnsignedShort(),
 242.213 -                                   StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
 242.214 -        } else if (frameType == FULL_FRAME) {
 242.215 -            // full_frame
 242.216 -            int offsetDelta = in.readUnsignedShort();
 242.217 -            int locals_size = in.readUnsignedShort();
 242.218 -            int[] locals = StackMapData.readTypeArray(in, locals_size, method);
 242.219 -            int stack_size = in.readUnsignedShort();
 242.220 -            int[] stack = StackMapData.readTypeArray(in, stack_size, method);
 242.221 -            return new FullFrame(offsetDelta, locals, stack);
 242.222 -        } else {
 242.223 -            throw new ClassFormatError("unrecognized frame_type in StackMapTable");
 242.224 -        }
 242.225 -    }
 242.226 -}
   243.1 --- a/rt/javap/src/main/java/org/apidesign/javap/TrapData.java	Wed Feb 27 17:50:47 2013 +0100
   243.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   243.3 @@ -1,62 +0,0 @@
   243.4 -/*
   243.5 - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
   243.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   243.7 - *
   243.8 - * This code is free software; you can redistribute it and/or modify it
   243.9 - * under the terms of the GNU General Public License version 2 only, as
  243.10 - * published by the Free Software Foundation.  Oracle designates this
  243.11 - * particular file as subject to the "Classpath" exception as provided
  243.12 - * by Oracle in the LICENSE file that accompanied this code.
  243.13 - *
  243.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  243.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  243.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  243.17 - * version 2 for more details (a copy is included in the LICENSE file that
  243.18 - * accompanied this code).
  243.19 - *
  243.20 - * You should have received a copy of the GNU General Public License version
  243.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  243.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  243.23 - *
  243.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  243.25 - * or visit www.oracle.com if you need additional information or have any
  243.26 - * questions.
  243.27 - */
  243.28 -
  243.29 -
  243.30 -package org.apidesign.javap;
  243.31 -
  243.32 -import java.io.*;
  243.33 -
  243.34 -/**
  243.35 - * Stores exception table data in code attribute.
  243.36 - *
  243.37 - * @author  Sucheta Dambalkar (Adopted code from jdis)
  243.38 - */
  243.39 -public final class TrapData {
  243.40 -  public final short start_pc;
  243.41 -  public final short end_pc;
  243.42 -  public final short handler_pc;
  243.43 -  public final short catch_cpx;
  243.44 -  final int num;
  243.45 -
  243.46 -
  243.47 -    /**
  243.48 -     * Read and store exception table data in code attribute.
  243.49 -     */
  243.50 -    TrapData(DataInputStream in, int num) throws IOException {
  243.51 -        this.num=num;
  243.52 -        start_pc = in.readShort();
  243.53 -        end_pc=in.readShort();
  243.54 -        handler_pc=in.readShort();
  243.55 -        catch_cpx=in.readShort();
  243.56 -    }
  243.57 -
  243.58 -    /**
  243.59 -     * returns recommended identifier
  243.60 -     */
  243.61 -    public String ident() {
  243.62 -        return "t"+num;
  243.63 -    }
  243.64 -
  243.65 -}
   244.1 --- a/rt/javap/src/main/java/org/apidesign/javap/TrapDataIterator.java	Wed Feb 27 17:50:47 2013 +0100
   244.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   244.3 @@ -1,114 +0,0 @@
   244.4 -/**
   244.5 - * Back 2 Browser Bytecode Translator
   244.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   244.7 - *
   244.8 - * This program is free software: you can redistribute it and/or modify
   244.9 - * it under the terms of the GNU General Public License as published by
  244.10 - * the Free Software Foundation, version 2 of the License.
  244.11 - *
  244.12 - * This program is distributed in the hope that it will be useful,
  244.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  244.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  244.15 - * GNU General Public License for more details.
  244.16 - *
  244.17 - * You should have received a copy of the GNU General Public License
  244.18 - * along with this program. Look for COPYING file in the top folder.
  244.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  244.20 - */
  244.21 -package org.apidesign.javap;
  244.22 -
  244.23 -/**
  244.24 - *
  244.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  244.26 - */
  244.27 -public final class TrapDataIterator {
  244.28 -    private final Hashtable exStart = new Hashtable();
  244.29 -    private final Hashtable exStop = new Hashtable();
  244.30 -    private TrapData[] current = new TrapData[10];
  244.31 -    private int currentCount;
  244.32 -    
  244.33 -    TrapDataIterator(Vector exceptionTable) {
  244.34 -        for (int i=0 ; i < exceptionTable.size(); i++) {
  244.35 -            final TrapData td = (TrapData)exceptionTable.elementAt(i);
  244.36 -            put(exStart, td.start_pc, td);
  244.37 -            put(exStop, td.end_pc, td);
  244.38 -        }
  244.39 -    }
  244.40 -    
  244.41 -    private static void put(Hashtable h, short key, TrapData td) {
  244.42 -        Short s = Short.valueOf((short)key);
  244.43 -        Vector v = (Vector) h.get(s);
  244.44 -        if (v == null) {
  244.45 -            v = new Vector(1);
  244.46 -            h.put(s, v);
  244.47 -        }
  244.48 -        v.add(td);
  244.49 -    }
  244.50 -    
  244.51 -    private boolean processAll(Hashtable h, Short key, boolean add) {
  244.52 -        boolean change = false;
  244.53 -        Vector v = (Vector)h.get(key);
  244.54 -        if (v != null) {
  244.55 -            int s = v.size();
  244.56 -            for (int i = 0; i < s; i++) {
  244.57 -                TrapData td = (TrapData)v.elementAt(i);
  244.58 -                if (add) {
  244.59 -                    add(td);
  244.60 -                    change = true;
  244.61 -                } else {
  244.62 -                    remove(td);
  244.63 -                    change = true;
  244.64 -                }
  244.65 -            }
  244.66 -        }
  244.67 -        return change;
  244.68 -    }
  244.69 -    
  244.70 -    public boolean advanceTo(int i) {
  244.71 -        Short s = Short.valueOf((short)i);
  244.72 -        boolean ch1 = processAll(exStart, s, true);
  244.73 -        boolean ch2 = processAll(exStop, s, false);
  244.74 -        return ch1 || ch2;
  244.75 -    }
  244.76 -
  244.77 -    public boolean useTry() {
  244.78 -        return currentCount > 0;
  244.79 -    }
  244.80 -
  244.81 -    public TrapData[] current() {
  244.82 -        TrapData[] copy = new TrapData[currentCount];
  244.83 -        for (int i = 0; i < currentCount; i++) {
  244.84 -            copy[i] = current[i];
  244.85 -        }
  244.86 -        return copy;
  244.87 -    }
  244.88 -
  244.89 -    private void add(TrapData e) {
  244.90 -        if (currentCount == current.length) {
  244.91 -            TrapData[] data = new TrapData[currentCount * 2];
  244.92 -            for (int i = 0; i < currentCount; i++) {
  244.93 -                data[i] = current[i];
  244.94 -            }
  244.95 -            current = data;
  244.96 -        }
  244.97 -        current[currentCount++] = e;
  244.98 -    }
  244.99 -
 244.100 -    private void remove(TrapData e) {
 244.101 -        if (currentCount == 0) {
 244.102 -            return;
 244.103 -        }
 244.104 -        int from = 0;
 244.105 -        while (from < currentCount) {
 244.106 -            if (e == current[from++]) {
 244.107 -                break;
 244.108 -            }
 244.109 -        }
 244.110 -        while (from < currentCount) {
 244.111 -            current[from - 1] = current[from];
 244.112 -            current[from] = null;
 244.113 -            from++;
 244.114 -        }
 244.115 -        currentCount--;
 244.116 -    }
 244.117 -}
   245.1 --- a/rt/javap/src/main/java/org/apidesign/javap/TypeArray.java	Wed Feb 27 17:50:47 2013 +0100
   245.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   245.3 @@ -1,186 +0,0 @@
   245.4 -/*
   245.5 - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   245.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   245.7 - *
   245.8 - * This code is free software; you can redistribute it and/or modify it
   245.9 - * under the terms of the GNU General Public License version 2 only, as
  245.10 - * published by the Free Software Foundation.  Oracle designates this
  245.11 - * particular file as subject to the "Classpath" exception as provided
  245.12 - * by Oracle in the LICENSE file that accompanied this code.
  245.13 - *
  245.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
  245.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  245.16 - * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  245.17 - * version 2 for more details (a copy is included in the LICENSE file that
  245.18 - * accompanied this code).
  245.19 - *
  245.20 - * You should have received a copy of the GNU General Public License version
  245.21 - * 2 along with this work; if not, write to the Free Software Foundation,
  245.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  245.23 - *
  245.24 - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  245.25 - * or visit www.oracle.com if you need additional information or have any
  245.26 - * questions.
  245.27 - */
  245.28 -
  245.29 -package org.apidesign.javap;
  245.30 -
  245.31 -import static org.apidesign.javap.RuntimeConstants.ITEM_Bogus;
  245.32 -import static org.apidesign.javap.RuntimeConstants.ITEM_Integer;
  245.33 -import static org.apidesign.javap.RuntimeConstants.ITEM_Float;
  245.34 -import static org.apidesign.javap.RuntimeConstants.ITEM_Double;
  245.35 -import static org.apidesign.javap.RuntimeConstants.ITEM_Long;
  245.36 -import static org.apidesign.javap.RuntimeConstants.ITEM_Null;
  245.37 -import static org.apidesign.javap.RuntimeConstants.ITEM_InitObject;
  245.38 -import static org.apidesign.javap.RuntimeConstants.ITEM_Object;
  245.39 -import static org.apidesign.javap.RuntimeConstants.ITEM_NewObject;
  245.40 -
  245.41 -public final class TypeArray {
  245.42 -    private static final int CAPACITY_INCREMENT = 16;
  245.43 -
  245.44 -    private int[] types;
  245.45 -    private int size;
  245.46 -
  245.47 -    public TypeArray() {
  245.48 -    }
  245.49 -    
  245.50 -    public TypeArray(final TypeArray initialTypes) {
  245.51 -        setAll(initialTypes);
  245.52 -    }
  245.53 -
  245.54 -    public void add(final int newType) {
  245.55 -        ensureCapacity(size + 1);
  245.56 -        types[size++] = newType;
  245.57 -    }
  245.58 -
  245.59 -    public void addAll(final TypeArray newTypes) {
  245.60 -        addAll(newTypes.types, 0, newTypes.size);
  245.61 -    }
  245.62 -
  245.63 -    public void addAll(final int[] newTypes) {
  245.64 -        addAll(newTypes, 0, newTypes.length);
  245.65 -    }
  245.66 -
  245.67 -    public void addAll(final int[] newTypes,
  245.68 -                       final int offset,
  245.69 -                       final int count) {
  245.70 -        if (count > 0) {
  245.71 -            ensureCapacity(size + count);
  245.72 -            arraycopy(newTypes, offset, types, size, count);
  245.73 -            size += count;
  245.74 -        }
  245.75 -    }
  245.76 -
  245.77 -    public void set(final int index, final int newType) {
  245.78 -        types[index] = newType;
  245.79 -    }
  245.80 -
  245.81 -    public void setAll(final TypeArray newTypes) {
  245.82 -        setAll(newTypes.types, 0, newTypes.size);
  245.83 -    }
  245.84 -
  245.85 -    public void setAll(final int[] newTypes) {
  245.86 -        setAll(newTypes, 0, newTypes.length);
  245.87 -    }
  245.88 -
  245.89 -    public void setAll(final int[] newTypes,
  245.90 -                       final int offset,
  245.91 -                       final int count) {
  245.92 -        if (count > 0) {
  245.93 -            ensureCapacity(count);
  245.94 -            arraycopy(newTypes, offset, types, 0, count);
  245.95 -            size = count;
  245.96 -        } else {
  245.97 -            clear();
  245.98 -        }
  245.99 -    }
 245.100 -
 245.101 -    public void setSize(final int newSize) {
 245.102 -        if (size != newSize) {
 245.103 -            ensureCapacity(newSize);
 245.104 -
 245.105 -            for (int i = size; i < newSize; ++i) {
 245.106 -                types[i] = 0;
 245.107 -            }
 245.108 -            size = newSize;
 245.109 -        }
 245.110 -    }
 245.111 -
 245.112 -    public void clear() {
 245.113 -        size = 0;
 245.114 -    }
 245.115 -
 245.116 -    public int getSize() {
 245.117 -        return size;
 245.118 -    }
 245.119 -
 245.120 -    public int get(final int index) {
 245.121 -        return types[index];
 245.122 -    }
 245.123 -
 245.124 -    public static String typeString(final int type) {
 245.125 -        switch (type & 0xff) {
 245.126 -            case ITEM_Bogus:
 245.127 -                return "_top_";
 245.128 -            case ITEM_Integer:
 245.129 -                return "_int_";
 245.130 -            case ITEM_Float:
 245.131 -                return "_float_";
 245.132 -            case ITEM_Double:
 245.133 -                return "_double_";
 245.134 -            case ITEM_Long:
 245.135 -                return "_long_";
 245.136 -            case ITEM_Null:
 245.137 -                return "_null_";
 245.138 -            case ITEM_InitObject: // UninitializedThis
 245.139 -                return "_init_";
 245.140 -            case ITEM_Object:
 245.141 -                return "_object_";
 245.142 -            case ITEM_NewObject: // Uninitialized
 245.143 -                return "_new_";
 245.144 -            default:
 245.145 -                throw new IllegalArgumentException("Unknown type");
 245.146 -        }
 245.147 -    }
 245.148 -
 245.149 -    @Override
 245.150 -    public String toString() {
 245.151 -        final StringBuilder sb = new StringBuilder("[");
 245.152 -        if (size > 0) {
 245.153 -            sb.append(typeString(types[0]));
 245.154 -            for (int i = 1; i < size; ++i) {
 245.155 -                sb.append(", ");
 245.156 -                sb.append(typeString(types[i]));
 245.157 -            }
 245.158 -        }
 245.159 -
 245.160 -        return sb.append(']').toString();
 245.161 -    }
 245.162 -
 245.163 -    private void ensureCapacity(final int minCapacity) {
 245.164 -        if ((minCapacity == 0)
 245.165 -                || (types != null) && (minCapacity <= types.length)) {
 245.166 -            return;
 245.167 -        }
 245.168 -
 245.169 -        final int newCapacity =
 245.170 -                ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT)
 245.171 -                    * CAPACITY_INCREMENT;
 245.172 -        final int[] newTypes = new int[newCapacity];
 245.173 -
 245.174 -        if (size > 0) {
 245.175 -            arraycopy(types, 0, newTypes, 0, size);
 245.176 -        }
 245.177 -
 245.178 -        types = newTypes;
 245.179 -    }
 245.180 -
 245.181 -    // no System.arraycopy
 245.182 -    private void arraycopy(final int[] src, final int srcPos,
 245.183 -                           final int[] dest, final int destPos,
 245.184 -                           final int length) {
 245.185 -        for (int i = 0; i < length; ++i) {
 245.186 -            dest[destPos + i] = src[srcPos + i];
 245.187 -        }
 245.188 -    }
 245.189 -}
   246.1 --- a/rt/javap/src/main/java/org/apidesign/javap/Vector.java	Wed Feb 27 17:50:47 2013 +0100
   246.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   246.3 @@ -1,89 +0,0 @@
   246.4 -/**
   246.5 - * Back 2 Browser Bytecode Translator
   246.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   246.7 - *
   246.8 - * This program is free software: you can redistribute it and/or modify
   246.9 - * it under the terms of the GNU General Public License as published by
  246.10 - * the Free Software Foundation, version 2 of the License.
  246.11 - *
  246.12 - * This program is distributed in the hope that it will be useful,
  246.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  246.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  246.15 - * GNU General Public License for more details.
  246.16 - *
  246.17 - * You should have received a copy of the GNU General Public License
  246.18 - * along with this program. Look for COPYING file in the top folder.
  246.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  246.20 - */
  246.21 -package org.apidesign.javap;
  246.22 -
  246.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  246.24 -import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
  246.25 -
  246.26 -/** A JavaScript ready replacement for java.util.Vector
  246.27 - *
  246.28 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  246.29 - */
  246.30 -@JavaScriptPrototype(prototype = "new Array" )
  246.31 -final class Vector {
  246.32 -    private Object[] arr;
  246.33 -    
  246.34 -    Vector() {
  246.35 -    }
  246.36 -
  246.37 -    Vector(int i) {
  246.38 -    }
  246.39 -
  246.40 -    void add(Object objectType) {
  246.41 -        addElement(objectType);
  246.42 -    }
  246.43 -    @JavaScriptBody(args = { "obj" }, body = 
  246.44 -        "this.push(obj);"
  246.45 -    )
  246.46 -    void addElement(Object obj) {
  246.47 -        final int s = size();
  246.48 -        setSize(s + 1);
  246.49 -        setElementAt(obj, s);
  246.50 -    }
  246.51 -
  246.52 -    @JavaScriptBody(args = { }, body = 
  246.53 -        "return this.length;"
  246.54 -    )
  246.55 -    int size() {
  246.56 -        return arr == null ? 0 : arr.length;
  246.57 -    }
  246.58 -
  246.59 -    @JavaScriptBody(args = { "newArr" }, body =
  246.60 -        "for (var i = 0; i < this.length; i++) {\n"
  246.61 -      + "  newArr[i] = this[i];\n"
  246.62 -      + "}\n")
  246.63 -    void copyInto(Object[] newArr) {
  246.64 -        if (arr == null) {
  246.65 -            return;
  246.66 -        }
  246.67 -        int min = Math.min(newArr.length, arr.length);
  246.68 -        for (int i = 0; i < min; i++) {
  246.69 -            newArr[i] = arr[i];
  246.70 -        }
  246.71 -    }
  246.72 -
  246.73 -    @JavaScriptBody(args = { "index" }, body =
  246.74 -        "return this[index];"
  246.75 -    )
  246.76 -    Object elementAt(int index) {
  246.77 -        return arr[index];
  246.78 -    }
  246.79 -
  246.80 -    private void setSize(int len) {
  246.81 -        Object[] newArr = new Object[len];
  246.82 -        copyInto(newArr);
  246.83 -        arr = newArr;
  246.84 -    }
  246.85 -
  246.86 -    @JavaScriptBody(args = { "val", "index" }, body = 
  246.87 -        "this[index] = val;"
  246.88 -    )
  246.89 -    void setElementAt(Object val, int index) {
  246.90 -        arr[index] = val;
  246.91 -    }
  246.92 -}
   247.1 --- a/rt/launcher/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   247.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   247.3 @@ -1,57 +0,0 @@
   247.4 -<?xml version="1.0"?>
   247.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   247.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   247.7 -  <modelVersion>4.0.0</modelVersion>
   247.8 -  <parent>
   247.9 -    <groupId>org.apidesign.bck2brwsr</groupId>
  247.10 -    <artifactId>rt</artifactId>
  247.11 -    <version>0.3-SNAPSHOT</version>
  247.12 -  </parent>
  247.13 -  <groupId>org.apidesign.bck2brwsr</groupId>
  247.14 -  <artifactId>launcher</artifactId>
  247.15 -  <version>0.3-SNAPSHOT</version>
  247.16 -  <name>Bck2Brwsr Launcher</name>
  247.17 -  <url>http://maven.apache.org</url>
  247.18 -    <build>
  247.19 -        <plugins>
  247.20 -            <plugin>
  247.21 -                <groupId>org.apache.maven.plugins</groupId>
  247.22 -                <artifactId>maven-compiler-plugin</artifactId>
  247.23 -                <version>2.3.2</version>
  247.24 -                <configuration>
  247.25 -                    <source>1.7</source>
  247.26 -                    <target>1.7</target>
  247.27 -                </configuration>
  247.28 -            </plugin>
  247.29 -            <plugin>
  247.30 -                <groupId>org.apache.maven.plugins</groupId>
  247.31 -                <artifactId>maven-javadoc-plugin</artifactId>
  247.32 -                <version>2.8.1</version>
  247.33 -                <configuration>
  247.34 -                    <excludePackageNames>org.apidesign.bck2brwsr.launcher.impl</excludePackageNames>
  247.35 -                </configuration>
  247.36 -            </plugin>
  247.37 -        </plugins>
  247.38 -    </build>
  247.39 -    <properties>
  247.40 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  247.41 -  </properties>
  247.42 -  <dependencies>
  247.43 -    <dependency>
  247.44 -      <groupId>junit</groupId>
  247.45 -      <artifactId>junit</artifactId>
  247.46 -      <version>3.8.1</version>
  247.47 -      <scope>test</scope>
  247.48 -    </dependency>
  247.49 -    <dependency>
  247.50 -      <groupId>org.glassfish.grizzly</groupId>
  247.51 -      <artifactId>grizzly-http-server</artifactId>
  247.52 -      <version>2.2.19</version>
  247.53 -    </dependency>
  247.54 -    <dependency>
  247.55 -      <groupId>${project.groupId}</groupId>
  247.56 -      <artifactId>vm4brwsr</artifactId>
  247.57 -      <version>${project.version}</version>
  247.58 -    </dependency>
  247.59 -  </dependencies>
  247.60 -</project>
   248.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Bck2BrwsrLauncher.java	Wed Feb 27 17:50:47 2013 +0100
   248.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   248.3 @@ -1,559 +0,0 @@
   248.4 -/**
   248.5 - * Back 2 Browser Bytecode Translator
   248.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   248.7 - *
   248.8 - * This program is free software: you can redistribute it and/or modify
   248.9 - * it under the terms of the GNU General Public License as published by
  248.10 - * the Free Software Foundation, version 2 of the License.
  248.11 - *
  248.12 - * This program is distributed in the hope that it will be useful,
  248.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  248.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  248.15 - * GNU General Public License for more details.
  248.16 - *
  248.17 - * You should have received a copy of the GNU General Public License
  248.18 - * along with this program. Look for COPYING file in the top folder.
  248.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  248.20 - */
  248.21 -package org.apidesign.bck2brwsr.launcher;
  248.22 -
  248.23 -import java.io.Closeable;
  248.24 -import java.io.File;
  248.25 -import java.io.IOException;
  248.26 -import java.io.InputStream;
  248.27 -import java.io.InterruptedIOException;
  248.28 -import java.io.OutputStream;
  248.29 -import java.io.Writer;
  248.30 -import java.net.URI;
  248.31 -import java.net.URISyntaxException;
  248.32 -import java.net.URL;
  248.33 -import java.util.ArrayList;
  248.34 -import java.util.Arrays;
  248.35 -import java.util.Enumeration;
  248.36 -import java.util.LinkedHashSet;
  248.37 -import java.util.List;
  248.38 -import java.util.Set;
  248.39 -import java.util.concurrent.BlockingQueue;
  248.40 -import java.util.concurrent.CountDownLatch;
  248.41 -import java.util.concurrent.LinkedBlockingQueue;
  248.42 -import java.util.concurrent.TimeUnit;
  248.43 -import java.util.logging.Level;
  248.44 -import java.util.logging.Logger;
  248.45 -import org.apidesign.bck2brwsr.launcher.InvocationContext.Resource;
  248.46 -import org.apidesign.vm4brwsr.Bck2Brwsr;
  248.47 -import org.glassfish.grizzly.PortRange;
  248.48 -import org.glassfish.grizzly.http.server.HttpHandler;
  248.49 -import org.glassfish.grizzly.http.server.HttpServer;
  248.50 -import org.glassfish.grizzly.http.server.NetworkListener;
  248.51 -import org.glassfish.grizzly.http.server.Request;
  248.52 -import org.glassfish.grizzly.http.server.Response;
  248.53 -import org.glassfish.grizzly.http.server.ServerConfiguration;
  248.54 -import org.glassfish.grizzly.http.util.HttpStatus;
  248.55 -
  248.56 -/**
  248.57 - * Lightweight server to launch Bck2Brwsr applications and tests.
  248.58 - * Supports execution in native browser as well as Java's internal 
  248.59 - * execution engine.
  248.60 - */
  248.61 -final class Bck2BrwsrLauncher extends Launcher implements Closeable {
  248.62 -    private static final Logger LOG = Logger.getLogger(Bck2BrwsrLauncher.class.getName());
  248.63 -    private static final InvocationContext END = new InvocationContext(null, null, null);
  248.64 -    private final Set<ClassLoader> loaders = new LinkedHashSet<>();
  248.65 -    private final BlockingQueue<InvocationContext> methods = new LinkedBlockingQueue<>();
  248.66 -    private long timeOut;
  248.67 -    private final Res resources = new Res();
  248.68 -    private final String cmd;
  248.69 -    private Object[] brwsr;
  248.70 -    private HttpServer server;
  248.71 -    private CountDownLatch wait;
  248.72 -    
  248.73 -    public Bck2BrwsrLauncher(String cmd) {
  248.74 -        this.cmd = cmd;
  248.75 -    }
  248.76 -    
  248.77 -    @Override
  248.78 -    InvocationContext runMethod(InvocationContext c) throws IOException {
  248.79 -        loaders.add(c.clazz.getClassLoader());
  248.80 -        methods.add(c);
  248.81 -        try {
  248.82 -            c.await(timeOut);
  248.83 -        } catch (InterruptedException ex) {
  248.84 -            throw new IOException(ex);
  248.85 -        }
  248.86 -        return c;
  248.87 -    }
  248.88 -    
  248.89 -    public void setTimeout(long ms) {
  248.90 -        timeOut = ms;
  248.91 -    }
  248.92 -    
  248.93 -    public void addClassLoader(ClassLoader url) {
  248.94 -        this.loaders.add(url);
  248.95 -    }
  248.96 -
  248.97 -    public void showURL(String startpage) throws IOException {
  248.98 -        if (!startpage.startsWith("/")) {
  248.99 -            startpage = "/" + startpage;
 248.100 -        }
 248.101 -        HttpServer s = initServer(".", true);
 248.102 -        int last = startpage.lastIndexOf('/');
 248.103 -        String simpleName = startpage.substring(last);
 248.104 -        s.getServerConfiguration().addHttpHandler(new Page(resources, startpage), simpleName);
 248.105 -        s.getServerConfiguration().addHttpHandler(new Page(resources, null), "/");
 248.106 -        try {
 248.107 -            launchServerAndBrwsr(s, simpleName);
 248.108 -        } catch (URISyntaxException | InterruptedException ex) {
 248.109 -            throw new IOException(ex);
 248.110 -        }
 248.111 -    }
 248.112 -
 248.113 -    void showDirectory(File dir, String startpage) throws IOException {
 248.114 -        if (!startpage.startsWith("/")) {
 248.115 -            startpage = "/" + startpage;
 248.116 -        }
 248.117 -        HttpServer s = initServer(dir.getPath(), false);
 248.118 -        try {
 248.119 -            launchServerAndBrwsr(s, startpage);
 248.120 -        } catch (URISyntaxException | InterruptedException ex) {
 248.121 -            throw new IOException(ex);
 248.122 -        }
 248.123 -    }
 248.124 -
 248.125 -    @Override
 248.126 -    public void initialize() throws IOException {
 248.127 -        try {
 248.128 -            executeInBrowser();
 248.129 -        } catch (InterruptedException ex) {
 248.130 -            final InterruptedIOException iio = new InterruptedIOException(ex.getMessage());
 248.131 -            iio.initCause(ex);
 248.132 -            throw iio;
 248.133 -        } catch (Exception ex) {
 248.134 -            if (ex instanceof IOException) {
 248.135 -                throw (IOException)ex;
 248.136 -            }
 248.137 -            if (ex instanceof RuntimeException) {
 248.138 -                throw (RuntimeException)ex;
 248.139 -            }
 248.140 -            throw new IOException(ex);
 248.141 -        }
 248.142 -    }
 248.143 -    
 248.144 -    private HttpServer initServer(String path, boolean addClasses) throws IOException {
 248.145 -        HttpServer s = HttpServer.createSimpleServer(path, new PortRange(8080, 65535));
 248.146 -
 248.147 -        final ServerConfiguration conf = s.getServerConfiguration();
 248.148 -        if (addClasses) {
 248.149 -            conf.addHttpHandler(new VM(resources), "/bck2brwsr.js");
 248.150 -            conf.addHttpHandler(new Classes(resources), "/classes/");
 248.151 -        }
 248.152 -        return s;
 248.153 -    }
 248.154 -    
 248.155 -    private void executeInBrowser() throws InterruptedException, URISyntaxException, IOException {
 248.156 -        wait = new CountDownLatch(1);
 248.157 -        server = initServer(".", true);
 248.158 -        final ServerConfiguration conf = server.getServerConfiguration();
 248.159 -        
 248.160 -        class DynamicResourceHandler extends HttpHandler {
 248.161 -            private final InvocationContext ic;
 248.162 -            public DynamicResourceHandler(InvocationContext ic) {
 248.163 -                if (ic == null || ic.resources.isEmpty()) {
 248.164 -                    throw new NullPointerException();
 248.165 -                }
 248.166 -                this.ic = ic;
 248.167 -                for (Resource r : ic.resources) {
 248.168 -                    conf.addHttpHandler(this, r.httpPath);
 248.169 -                }
 248.170 -            }
 248.171 -
 248.172 -            public void close() {
 248.173 -                conf.removeHttpHandler(this);
 248.174 -            }
 248.175 -            
 248.176 -            @Override
 248.177 -            public void service(Request request, Response response) throws Exception {
 248.178 -                for (Resource r : ic.resources) {
 248.179 -                    if (r.httpPath.equals(request.getRequestURI())) {
 248.180 -                        LOG.log(Level.INFO, "Serving HttpResource for {0}", request.getRequestURI());
 248.181 -                        response.setContentType(r.httpType);
 248.182 -                        copyStream(r.httpContent, response.getOutputStream(), null);
 248.183 -                    }
 248.184 -                }
 248.185 -            }
 248.186 -        }
 248.187 -        
 248.188 -        conf.addHttpHandler(new Page(resources, 
 248.189 -            "org/apidesign/bck2brwsr/launcher/harness.xhtml"
 248.190 -        ), "/execute");
 248.191 -        
 248.192 -        conf.addHttpHandler(new HttpHandler() {
 248.193 -            int cnt;
 248.194 -            List<InvocationContext> cases = new ArrayList<>();
 248.195 -            DynamicResourceHandler prev;
 248.196 -            @Override
 248.197 -            public void service(Request request, Response response) throws Exception {
 248.198 -                String id = request.getParameter("request");
 248.199 -                String value = request.getParameter("result");
 248.200 -                
 248.201 -                
 248.202 -                InvocationContext mi = null;
 248.203 -                int caseNmbr = -1;
 248.204 -                
 248.205 -                if (id != null && value != null) {
 248.206 -                    LOG.log(Level.INFO, "Received result for case {0} = {1}", new Object[]{id, value});
 248.207 -                    value = decodeURL(value);
 248.208 -                    int indx = Integer.parseInt(id);
 248.209 -                    cases.get(indx).result(value, null);
 248.210 -                    if (++indx < cases.size()) {
 248.211 -                        mi = cases.get(indx);
 248.212 -                        LOG.log(Level.INFO, "Re-executing case {0}", indx);
 248.213 -                        caseNmbr = indx;
 248.214 -                    }
 248.215 -                } else {
 248.216 -                    if (!cases.isEmpty()) {
 248.217 -                        LOG.info("Re-executing test cases");
 248.218 -                        mi = cases.get(0);
 248.219 -                        caseNmbr = 0;
 248.220 -                    }
 248.221 -                }
 248.222 -                
 248.223 -                if (prev != null) {
 248.224 -                    prev.close();
 248.225 -                    prev = null;
 248.226 -                }
 248.227 -                
 248.228 -                if (mi == null) {
 248.229 -                    mi = methods.take();
 248.230 -                    caseNmbr = cnt++;
 248.231 -                }
 248.232 -                if (mi == END) {
 248.233 -                    response.getWriter().write("");
 248.234 -                    wait.countDown();
 248.235 -                    cnt = 0;
 248.236 -                    LOG.log(Level.INFO, "End of data reached. Exiting.");
 248.237 -                    return;
 248.238 -                }
 248.239 -                
 248.240 -                if (!mi.resources.isEmpty()) {
 248.241 -                    prev = new DynamicResourceHandler(mi);
 248.242 -                }
 248.243 -                
 248.244 -                cases.add(mi);
 248.245 -                final String cn = mi.clazz.getName();
 248.246 -                final String mn = mi.methodName;
 248.247 -                LOG.log(Level.INFO, "Request for {0} case. Sending {1}.{2}", new Object[]{caseNmbr, cn, mn});
 248.248 -                response.getWriter().write("{"
 248.249 -                    + "className: '" + cn + "', "
 248.250 -                    + "methodName: '" + mn + "', "
 248.251 -                    + "request: " + caseNmbr
 248.252 -                );
 248.253 -                if (mi.html != null) {
 248.254 -                    response.getWriter().write(", html: '");
 248.255 -                    response.getWriter().write(encodeJSON(mi.html));
 248.256 -                    response.getWriter().write("'");
 248.257 -                }
 248.258 -                response.getWriter().write("}");
 248.259 -            }
 248.260 -        }, "/data");
 248.261 -
 248.262 -        this.brwsr = launchServerAndBrwsr(server, "/execute");
 248.263 -    }
 248.264 -    
 248.265 -    private static String encodeJSON(String in) {
 248.266 -        StringBuilder sb = new StringBuilder();
 248.267 -        for (int i = 0; i < in.length(); i++) {
 248.268 -            char ch = in.charAt(i);
 248.269 -            if (ch < 32 || ch == '\'' || ch == '"') {
 248.270 -                sb.append("\\u");
 248.271 -                String hs = "0000" + Integer.toHexString(ch);
 248.272 -                hs = hs.substring(hs.length() - 4);
 248.273 -                sb.append(hs);
 248.274 -            } else {
 248.275 -                sb.append(ch);
 248.276 -            }
 248.277 -        }
 248.278 -        return sb.toString();
 248.279 -    }
 248.280 -    
 248.281 -    @Override
 248.282 -    public void shutdown() throws IOException {
 248.283 -        methods.offer(END);
 248.284 -        for (;;) {
 248.285 -            int prev = methods.size();
 248.286 -            try {
 248.287 -                if (wait != null && wait.await(timeOut, TimeUnit.MILLISECONDS)) {
 248.288 -                    break;
 248.289 -                }
 248.290 -            } catch (InterruptedException ex) {
 248.291 -                throw new IOException(ex);
 248.292 -            }
 248.293 -            if (prev == methods.size()) {
 248.294 -                LOG.log(
 248.295 -                    Level.WARNING, 
 248.296 -                    "Timeout and no test has been executed meanwhile (at {0}). Giving up.", 
 248.297 -                    methods.size()
 248.298 -                );
 248.299 -                break;
 248.300 -            }
 248.301 -            LOG.log(Level.INFO, 
 248.302 -                "Timeout, but tests got from {0} to {1}. Trying again.", 
 248.303 -                new Object[]{prev, methods.size()}
 248.304 -            );
 248.305 -        }
 248.306 -        stopServerAndBrwsr(server, brwsr);
 248.307 -    }
 248.308 -    
 248.309 -    static void copyStream(InputStream is, OutputStream os, String baseURL, String... params) throws IOException {
 248.310 -        for (;;) {
 248.311 -            int ch = is.read();
 248.312 -            if (ch == -1) {
 248.313 -                break;
 248.314 -            }
 248.315 -            if (ch == '$' && params.length > 0) {
 248.316 -                int cnt = is.read() - '0';
 248.317 -                if (cnt == 'U' - '0') {
 248.318 -                    os.write(baseURL.getBytes("UTF-8"));
 248.319 -                }
 248.320 -                if (cnt >= 0 && cnt < params.length) {
 248.321 -                    os.write(params[cnt].getBytes("UTF-8"));
 248.322 -                }
 248.323 -            } else {
 248.324 -                os.write(ch);
 248.325 -            }
 248.326 -        }
 248.327 -    }
 248.328 -
 248.329 -    private Object[] launchServerAndBrwsr(HttpServer server, final String page) throws IOException, URISyntaxException, InterruptedException {
 248.330 -        server.start();
 248.331 -        NetworkListener listener = server.getListeners().iterator().next();
 248.332 -        int port = listener.getPort();
 248.333 -        
 248.334 -        URI uri = new URI("http://localhost:" + port + page);
 248.335 -        LOG.log(Level.INFO, "Showing {0}", uri);
 248.336 -        if (cmd == null) {
 248.337 -            try {
 248.338 -                LOG.log(Level.INFO, "Trying Desktop.browse on {0} {2} by {1}", new Object[] {
 248.339 -                    System.getProperty("java.vm.name"),
 248.340 -                    System.getProperty("java.vm.vendor"),
 248.341 -                    System.getProperty("java.vm.version"),
 248.342 -                });
 248.343 -                java.awt.Desktop.getDesktop().browse(uri);
 248.344 -                LOG.log(Level.INFO, "Desktop.browse successfully finished");
 248.345 -                return null;
 248.346 -            } catch (UnsupportedOperationException ex) {
 248.347 -                LOG.log(Level.INFO, "Desktop.browse not supported: {0}", ex.getMessage());
 248.348 -                LOG.log(Level.FINE, null, ex);
 248.349 -            }
 248.350 -        }
 248.351 -        {
 248.352 -            String cmdName = cmd == null ? "xdg-open" : cmd;
 248.353 -            String[] cmdArr = { 
 248.354 -                cmdName, uri.toString()
 248.355 -            };
 248.356 -            LOG.log(Level.INFO, "Launching {0}", Arrays.toString(cmdArr));
 248.357 -            final Process process = Runtime.getRuntime().exec(cmdArr);
 248.358 -            return new Object[] { process, null };
 248.359 -        }
 248.360 -    }
 248.361 -    
 248.362 -    private static String decodeURL(String s) {
 248.363 -        for (;;) {
 248.364 -            int pos = s.indexOf('%');
 248.365 -            if (pos == -1) {
 248.366 -                return s;
 248.367 -            }
 248.368 -            int i = Integer.parseInt(s.substring(pos + 1, pos + 2), 16);
 248.369 -            s = s.substring(0, pos) + (char)i + s.substring(pos + 2);
 248.370 -        }
 248.371 -    }
 248.372 -    
 248.373 -    private void stopServerAndBrwsr(HttpServer server, Object[] brwsr) throws IOException {
 248.374 -        if (brwsr == null) {
 248.375 -            return;
 248.376 -        }
 248.377 -        Process process = (Process)brwsr[0];
 248.378 -        
 248.379 -        server.stop();
 248.380 -        InputStream stdout = process.getInputStream();
 248.381 -        InputStream stderr = process.getErrorStream();
 248.382 -        drain("StdOut", stdout);
 248.383 -        drain("StdErr", stderr);
 248.384 -        process.destroy();
 248.385 -        int res;
 248.386 -        try {
 248.387 -            res = process.waitFor();
 248.388 -        } catch (InterruptedException ex) {
 248.389 -            throw new IOException(ex);
 248.390 -        }
 248.391 -        LOG.log(Level.INFO, "Exit code: {0}", res);
 248.392 -
 248.393 -        deleteTree((File)brwsr[1]);
 248.394 -    }
 248.395 -    
 248.396 -    private static void drain(String name, InputStream is) throws IOException {
 248.397 -        int av = is.available();
 248.398 -        if (av > 0) {
 248.399 -            StringBuilder sb = new StringBuilder();
 248.400 -            sb.append("v== ").append(name).append(" ==v\n");
 248.401 -            while (av-- > 0) {
 248.402 -                sb.append((char)is.read());
 248.403 -            }
 248.404 -            sb.append("\n^== ").append(name).append(" ==^");
 248.405 -            LOG.log(Level.INFO, sb.toString());
 248.406 -        }
 248.407 -    }
 248.408 -
 248.409 -    private void deleteTree(File file) {
 248.410 -        if (file == null) {
 248.411 -            return;
 248.412 -        }
 248.413 -        File[] arr = file.listFiles();
 248.414 -        if (arr != null) {
 248.415 -            for (File s : arr) {
 248.416 -                deleteTree(s);
 248.417 -            }
 248.418 -        }
 248.419 -        file.delete();
 248.420 -    }
 248.421 -
 248.422 -    @Override
 248.423 -    public void close() throws IOException {
 248.424 -        shutdown();
 248.425 -    }
 248.426 -
 248.427 -    private class Res implements Bck2Brwsr.Resources {
 248.428 -        @Override
 248.429 -        public InputStream get(String resource) throws IOException {
 248.430 -            for (ClassLoader l : loaders) {
 248.431 -                URL u = null;
 248.432 -                Enumeration<URL> en = l.getResources(resource);
 248.433 -                while (en.hasMoreElements()) {
 248.434 -                    u = en.nextElement();
 248.435 -                }
 248.436 -                if (u != null) {
 248.437 -                    return u.openStream();
 248.438 -                }
 248.439 -            }
 248.440 -            throw new IOException("Can't find " + resource);
 248.441 -        }
 248.442 -    }
 248.443 -
 248.444 -    private static class Page extends HttpHandler {
 248.445 -        private final String resource;
 248.446 -        private final String[] args;
 248.447 -        private final Res res;
 248.448 -        
 248.449 -        public Page(Res res, String resource, String... args) {
 248.450 -            this.res = res;
 248.451 -            this.resource = resource;
 248.452 -            this.args = args.length == 0 ? new String[] { "$0" } : args;
 248.453 -        }
 248.454 -
 248.455 -        @Override
 248.456 -        public void service(Request request, Response response) throws Exception {
 248.457 -            String r = resource;
 248.458 -            if (r == null) {
 248.459 -                r = request.getHttpHandlerPath();
 248.460 -            }
 248.461 -            if (r.startsWith("/")) {
 248.462 -                r = r.substring(1);
 248.463 -            }
 248.464 -            String[] replace = {};
 248.465 -            if (r.endsWith(".html")) {
 248.466 -                response.setContentType("text/html");
 248.467 -                LOG.info("Content type text/html");
 248.468 -                replace = args;
 248.469 -            }
 248.470 -            if (r.endsWith(".xhtml")) {
 248.471 -                response.setContentType("application/xhtml+xml");
 248.472 -                LOG.info("Content type application/xhtml+xml");
 248.473 -                replace = args;
 248.474 -            }
 248.475 -            OutputStream os = response.getOutputStream();
 248.476 -            try (InputStream is = res.get(r)) {
 248.477 -                copyStream(is, os, request.getRequestURL().toString(), replace);
 248.478 -            } catch (IOException ex) {
 248.479 -                response.setDetailMessage(ex.getLocalizedMessage());
 248.480 -                response.setError();
 248.481 -                response.setStatus(404);
 248.482 -            }
 248.483 -        }
 248.484 -    }
 248.485 -
 248.486 -    private static class VM extends HttpHandler {
 248.487 -        private final String bck2brwsr;
 248.488 -
 248.489 -        public VM(Res loader) throws IOException {
 248.490 -            StringBuilder sb = new StringBuilder();
 248.491 -            Bck2Brwsr.generate(sb, loader);
 248.492 -            sb.append(
 248.493 -                  "(function WrapperVM(global) {"
 248.494 -                + "  function ldCls(res) {\n"
 248.495 -                + "    var request = new XMLHttpRequest();\n"
 248.496 -                + "    request.open('GET', '/classes/' + res, false);\n"
 248.497 -                + "    request.send();\n"
 248.498 -                + "    if (request.status !== 200) return null;\n"
 248.499 -                + "    var arr = eval('(' + request.responseText + ')');\n"
 248.500 -                + "    return arr;\n"
 248.501 -                + "  }\n"
 248.502 -                + "  var prevvm = global.bck2brwsr;\n"
 248.503 -                + "  global.bck2brwsr = function() {\n"
 248.504 -                + "    var args = Array.prototype.slice.apply(arguments);\n"
 248.505 -                + "    args.unshift(ldCls);\n"
 248.506 -                + "    return prevvm.apply(null, args);\n"
 248.507 -                + "  };\n"
 248.508 -                + "})(this);\n"
 248.509 -            );
 248.510 -            this.bck2brwsr = sb.toString();
 248.511 -        }
 248.512 -
 248.513 -        @Override
 248.514 -        public void service(Request request, Response response) throws Exception {
 248.515 -            response.setCharacterEncoding("UTF-8");
 248.516 -            response.setContentType("text/javascript");
 248.517 -            response.getWriter().write(bck2brwsr);
 248.518 -        }
 248.519 -    }
 248.520 -
 248.521 -    private static class Classes extends HttpHandler {
 248.522 -        private final Res loader;
 248.523 -
 248.524 -        public Classes(Res loader) {
 248.525 -            this.loader = loader;
 248.526 -        }
 248.527 -
 248.528 -        @Override
 248.529 -        public void service(Request request, Response response) throws Exception {
 248.530 -            String res = request.getHttpHandlerPath();
 248.531 -            if (res.startsWith("/")) {
 248.532 -                res = res.substring(1);
 248.533 -            }
 248.534 -            try (InputStream is = loader.get(res)) {
 248.535 -                response.setContentType("text/javascript");
 248.536 -                Writer w = response.getWriter();
 248.537 -                w.append("[");
 248.538 -                for (int i = 0;; i++) {
 248.539 -                    int b = is.read();
 248.540 -                    if (b == -1) {
 248.541 -                        break;
 248.542 -                    }
 248.543 -                    if (i > 0) {
 248.544 -                        w.append(", ");
 248.545 -                    }
 248.546 -                    if (i % 20 == 0) {
 248.547 -                        w.write("\n");
 248.548 -                    }
 248.549 -                    if (b > 127) {
 248.550 -                        b = b - 256;
 248.551 -                    }
 248.552 -                    w.append(Integer.toString(b));
 248.553 -                }
 248.554 -                w.append("\n]");
 248.555 -            } catch (IOException ex) {
 248.556 -                response.setStatus(HttpStatus.NOT_FOUND_404);
 248.557 -                response.setError();
 248.558 -                response.setDetailMessage(ex.getMessage());
 248.559 -            }
 248.560 -        }
 248.561 -    }
 248.562 -}
   249.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/InvocationContext.java	Wed Feb 27 17:50:47 2013 +0100
   249.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   249.3 @@ -1,110 +0,0 @@
   249.4 -/**
   249.5 - * Back 2 Browser Bytecode Translator
   249.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   249.7 - *
   249.8 - * This program is free software: you can redistribute it and/or modify
   249.9 - * it under the terms of the GNU General Public License as published by
  249.10 - * the Free Software Foundation, version 2 of the License.
  249.11 - *
  249.12 - * This program is distributed in the hope that it will be useful,
  249.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  249.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  249.15 - * GNU General Public License for more details.
  249.16 - *
  249.17 - * You should have received a copy of the GNU General Public License
  249.18 - * along with this program. Look for COPYING file in the top folder.
  249.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  249.20 - */
  249.21 -package org.apidesign.bck2brwsr.launcher;
  249.22 -
  249.23 -import java.io.IOException;
  249.24 -import java.io.InputStream;
  249.25 -import java.util.ArrayList;
  249.26 -import java.util.List;
  249.27 -import java.util.concurrent.CountDownLatch;
  249.28 -import java.util.concurrent.TimeUnit;
  249.29 -
  249.30 -/** Represents individual method invocation, its context and its result.
  249.31 - *
  249.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  249.33 - */
  249.34 -public final class InvocationContext {
  249.35 -    final CountDownLatch wait = new CountDownLatch(1);
  249.36 -    final Class<?> clazz;
  249.37 -    final String methodName;
  249.38 -    private final Launcher launcher;
  249.39 -    private String result;
  249.40 -    private Throwable exception;
  249.41 -    String html;
  249.42 -    final List<Resource> resources = new ArrayList<>();
  249.43 -
  249.44 -    InvocationContext(Launcher launcher, Class<?> clazz, String methodName) {
  249.45 -        this.launcher = launcher;
  249.46 -        this.clazz = clazz;
  249.47 -        this.methodName = methodName;
  249.48 -    }
  249.49 -    
  249.50 -    /** An HTML fragment to be available for the execution. Useful primarily when
  249.51 -     * executing in a browser via {@link Launcher#createBrowser(java.lang.String)}.
  249.52 -     * @param html the html fragment
  249.53 -     */
  249.54 -    public void setHtmlFragment(String html) {
  249.55 -        this.html = html;
  249.56 -    }
  249.57 -    
  249.58 -    /** HTTP resource to be available during execution. An invocation may
  249.59 -     * perform an HTTP query and obtain a resource relative to the page.
  249.60 -     */
  249.61 -    public void addHttpResource(String relativePath, String mimeType, InputStream content) {
  249.62 -        if (relativePath == null || mimeType == null || content == null) {
  249.63 -            throw new NullPointerException();
  249.64 -        }
  249.65 -        resources.add(new Resource(content, mimeType, relativePath));
  249.66 -    }
  249.67 -    
  249.68 -    /** Invokes the associated method. 
  249.69 -     * @return the textual result of the invocation
  249.70 -     */
  249.71 -    public String invoke() throws IOException {
  249.72 -        launcher.runMethod(this);
  249.73 -        return toString();
  249.74 -    }
  249.75 -    
  249.76 -    /** Obtains textual result of the invocation.
  249.77 -     * @return text representing the exception or result value
  249.78 -     */
  249.79 -    @Override
  249.80 -    public String toString() {
  249.81 -        if (exception != null) {
  249.82 -            return exception.toString();
  249.83 -        }
  249.84 -        return result;
  249.85 -    }
  249.86 -    
  249.87 -    /**
  249.88 -     * @param timeOut
  249.89 -     * @throws InterruptedException 
  249.90 -     */
  249.91 -    void await(long timeOut) throws InterruptedException {
  249.92 -        wait.await(timeOut, TimeUnit.MILLISECONDS);
  249.93 -    }
  249.94 -    
  249.95 -    void result(String r, Throwable e) {
  249.96 -        this.result = r;
  249.97 -        this.exception = e;
  249.98 -        wait.countDown();
  249.99 -    }
 249.100 -
 249.101 -
 249.102 -    static final class Resource {
 249.103 -        final InputStream httpContent;
 249.104 -        final String httpType;
 249.105 -        final String httpPath;
 249.106 -
 249.107 -        Resource(InputStream httpContent, String httpType, String httpPath) {
 249.108 -            this.httpContent = httpContent;
 249.109 -            this.httpType = httpType;
 249.110 -            this.httpPath = httpPath;
 249.111 -        }
 249.112 -    }
 249.113 -}
   250.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/JSLauncher.java	Wed Feb 27 17:50:47 2013 +0100
   250.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   250.3 @@ -1,132 +0,0 @@
   250.4 -/**
   250.5 - * Back 2 Browser Bytecode Translator
   250.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   250.7 - *
   250.8 - * This program is free software: you can redistribute it and/or modify
   250.9 - * it under the terms of the GNU General Public License as published by
  250.10 - * the Free Software Foundation, version 2 of the License.
  250.11 - *
  250.12 - * This program is distributed in the hope that it will be useful,
  250.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  250.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  250.15 - * GNU General Public License for more details.
  250.16 - *
  250.17 - * You should have received a copy of the GNU General Public License
  250.18 - * along with this program. Look for COPYING file in the top folder.
  250.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  250.20 - */
  250.21 -package org.apidesign.bck2brwsr.launcher;
  250.22 -
  250.23 -import org.apidesign.bck2brwsr.launcher.impl.Console;
  250.24 -import java.io.IOException;
  250.25 -import java.io.InputStream;
  250.26 -import java.net.URL;
  250.27 -import java.util.Enumeration;
  250.28 -import java.util.LinkedHashSet;
  250.29 -import java.util.Set;
  250.30 -import java.util.logging.Level;
  250.31 -import java.util.logging.Logger;
  250.32 -import javax.script.Invocable;
  250.33 -import javax.script.ScriptEngine;
  250.34 -import javax.script.ScriptEngineManager;
  250.35 -import javax.script.ScriptException;
  250.36 -import org.apidesign.vm4brwsr.Bck2Brwsr;
  250.37 -
  250.38 -/**
  250.39 - * Tests execution in Java's internal scripting engine.
  250.40 - */
  250.41 -final class JSLauncher extends Launcher {
  250.42 -    private static final Logger LOG = Logger.getLogger(JSLauncher.class.getName());
  250.43 -    private Set<ClassLoader> loaders = new LinkedHashSet<>();
  250.44 -    private final Res resources = new Res();
  250.45 -    private Invocable code;
  250.46 -    private StringBuilder codeSeq;
  250.47 -    private Object console;
  250.48 -    
  250.49 -    
  250.50 -    @Override InvocationContext runMethod(InvocationContext mi) {
  250.51 -        loaders.add(mi.clazz.getClassLoader());
  250.52 -        try {
  250.53 -            long time = System.currentTimeMillis();
  250.54 -            LOG.log(Level.FINE, "Invoking {0}.{1}", new Object[]{mi.clazz.getName(), mi.methodName});
  250.55 -            String res = code.invokeMethod(
  250.56 -                console,
  250.57 -                "invoke__Ljava_lang_String_2Ljava_lang_String_2Ljava_lang_String_2",
  250.58 -                mi.clazz.getName(), mi.methodName).toString();
  250.59 -            time = System.currentTimeMillis() - time;
  250.60 -            LOG.log(Level.FINE, "Resut of {0}.{1} = {2} in {3} ms", new Object[]{mi.clazz.getName(), mi.methodName, res, time});
  250.61 -            mi.result(res, null);
  250.62 -        } catch (ScriptException | NoSuchMethodException ex) {
  250.63 -            mi.result(null, ex);
  250.64 -        }
  250.65 -        return mi;
  250.66 -    }
  250.67 -    
  250.68 -    public void addClassLoader(ClassLoader url) {
  250.69 -        this.loaders.add(url);
  250.70 -    }
  250.71 -
  250.72 -    @Override
  250.73 -    public void initialize() throws IOException {
  250.74 -        try {
  250.75 -            initRhino();
  250.76 -        } catch (Exception ex) {
  250.77 -            if (ex instanceof IOException) {
  250.78 -                throw (IOException)ex;
  250.79 -            }
  250.80 -            if (ex instanceof RuntimeException) {
  250.81 -                throw (RuntimeException)ex;
  250.82 -            }
  250.83 -            throw new IOException(ex);
  250.84 -        }
  250.85 -    }
  250.86 -    
  250.87 -    private void initRhino() throws IOException, ScriptException, NoSuchMethodException {
  250.88 -        StringBuilder sb = new StringBuilder();
  250.89 -        Bck2Brwsr.generate(sb, new Res());
  250.90 -
  250.91 -        ScriptEngineManager sem = new ScriptEngineManager();
  250.92 -        ScriptEngine mach = sem.getEngineByExtension("js");
  250.93 -
  250.94 -        sb.append(
  250.95 -              "\nvar vm = new bck2brwsr(org.apidesign.bck2brwsr.launcher.impl.Console.read);"
  250.96 -            + "\nfunction initVM() { return vm; };"
  250.97 -            + "\n");
  250.98 -
  250.99 -        Object res = mach.eval(sb.toString());
 250.100 -        if (!(mach instanceof Invocable)) {
 250.101 -            throw new IOException("It is invocable object: " + res);
 250.102 -        }
 250.103 -        code = (Invocable) mach;
 250.104 -        codeSeq = sb;
 250.105 -        
 250.106 -        Object vm = code.invokeFunction("initVM");
 250.107 -        console = code.invokeMethod(vm, "loadClass", Console.class.getName());
 250.108 -    }
 250.109 -
 250.110 -    @Override
 250.111 -    public void shutdown() throws IOException {
 250.112 -    }
 250.113 -
 250.114 -    @Override
 250.115 -    public String toString() {
 250.116 -        return codeSeq.toString();
 250.117 -    }
 250.118 -    
 250.119 -    private class Res implements Bck2Brwsr.Resources {
 250.120 -        @Override
 250.121 -        public InputStream get(String resource) throws IOException {
 250.122 -            for (ClassLoader l : loaders) {
 250.123 -                URL u = null;
 250.124 -                Enumeration<URL> en = l.getResources(resource);
 250.125 -                while (en.hasMoreElements()) {
 250.126 -                    u = en.nextElement();
 250.127 -                }
 250.128 -                if (u != null) {
 250.129 -                    return u.openStream();
 250.130 -                }
 250.131 -            }
 250.132 -            throw new IOException("Can't find " + resource);
 250.133 -        }
 250.134 -    }
 250.135 -}
   251.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/Launcher.java	Wed Feb 27 17:50:47 2013 +0100
   251.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   251.3 @@ -1,115 +0,0 @@
   251.4 -/**
   251.5 - * Back 2 Browser Bytecode Translator
   251.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   251.7 - *
   251.8 - * This program is free software: you can redistribute it and/or modify
   251.9 - * it under the terms of the GNU General Public License as published by
  251.10 - * the Free Software Foundation, version 2 of the License.
  251.11 - *
  251.12 - * This program is distributed in the hope that it will be useful,
  251.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  251.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  251.15 - * GNU General Public License for more details.
  251.16 - *
  251.17 - * You should have received a copy of the GNU General Public License
  251.18 - * along with this program. Look for COPYING file in the top folder.
  251.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  251.20 - */
  251.21 -package org.apidesign.bck2brwsr.launcher;
  251.22 -
  251.23 -import java.io.Closeable;
  251.24 -import java.io.File;
  251.25 -import java.io.IOException;
  251.26 -import java.net.URLClassLoader;
  251.27 -import org.apidesign.vm4brwsr.Bck2Brwsr;
  251.28 -
  251.29 -/** An abstraction for executing tests in a Bck2Brwsr virtual machine.
  251.30 - * Either in {@linkm Launcher#createJavaScript JavaScript engine}, 
  251.31 - * or in {@linkm Launcher#createBrowser external browser}.
  251.32 - *
  251.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  251.34 - */
  251.35 -public abstract class Launcher {
  251.36 -
  251.37 -    Launcher() {
  251.38 -    }
  251.39 -
  251.40 -    /** Initializes the launcher. This may mean starting a web browser or
  251.41 -     * initializing execution engine.
  251.42 -     * @throws IOException if something goes wrong
  251.43 -     */
  251.44 -    public abstract void initialize() throws IOException;
  251.45 -    
  251.46 -    /** Shuts down the launcher.
  251.47 -     * @throws IOException if something goes wrong
  251.48 -     */
  251.49 -    public abstract void shutdown() throws IOException;
  251.50 -    
  251.51 -    
  251.52 -    /** Builds an invocation context. The context can later be customized
  251.53 -     * and {@link InvocationContext#invoke() invoked}.
  251.54 -     * 
  251.55 -     * @param clazz the class to execute method from
  251.56 -     * @param method the method to execute
  251.57 -     * @return the context pointing to the selected method
  251.58 -     */
  251.59 -    public InvocationContext createInvocation(Class<?> clazz, String method) {
  251.60 -        return new InvocationContext(this, clazz, method);
  251.61 -    }
  251.62 -    
  251.63 -
  251.64 -    /** Creates launcher that uses internal JavaScript engine (Rhino).
  251.65 -     * @return the launcher
  251.66 -     */
  251.67 -    public static Launcher createJavaScript() {
  251.68 -        final JSLauncher l = new JSLauncher();
  251.69 -        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
  251.70 -        return l;
  251.71 -    }
  251.72 -    
  251.73 -    /** Creates launcher that is using external browser.
  251.74 -     * 
  251.75 -     * @param cmd <code>null</code> to use <code>java.awt.Desktop</code> to show the launcher
  251.76 -     *    or a string to execute in an external process (with a parameter to the URL)
  251.77 -     * @return launcher executing in external browser.
  251.78 -     */
  251.79 -    public static Launcher createBrowser(String cmd) {
  251.80 -        final Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(cmd);
  251.81 -        l.addClassLoader(Bck2Brwsr.class.getClassLoader());
  251.82 -        l.setTimeout(180000);
  251.83 -        return l;
  251.84 -    }
  251.85 -    
  251.86 -    /** Starts an HTTP server which provides access to classes and resources
  251.87 -     * available in the <code>classes</code> URL and shows a start page
  251.88 -     * available as {@link ClassLoader#getResource(java.lang.String)} from the
  251.89 -     * provide classloader. Opens a browser with URL showing the start page.
  251.90 -     * 
  251.91 -     * @param classes classloader offering access to classes and resources
  251.92 -     * @param startpage page to show in the browser
  251.93 -     * @return interface that allows one to stop the server
  251.94 -     * @throws IOException if something goes wrong
  251.95 -     */
  251.96 -    public static Closeable showURL(URLClassLoader classes, String startpage) throws IOException {
  251.97 -        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
  251.98 -        l.addClassLoader(classes);
  251.99 -        l.showURL(startpage);
 251.100 -        return l;
 251.101 -    }
 251.102 -    /** Starts an HTTP server which provides access to certain directory.
 251.103 -     * The <code>startpage</code> should be relative location inside the root 
 251.104 -     * driecotry
 251.105 -     * Opens a browser with URL showing the start page.
 251.106 -     * 
 251.107 -     * @param directory the root directory on disk
 251.108 -     * @praam startpage relative path from the root to the page
 251.109 -     * @exception IOException if something goes wrong.
 251.110 -     */
 251.111 -    public static Closeable showDir(File directory, String startpage) throws IOException {
 251.112 -        Bck2BrwsrLauncher l = new Bck2BrwsrLauncher(null);
 251.113 -        l.showDirectory(directory, startpage);
 251.114 -        return l;
 251.115 -    }
 251.116 -
 251.117 -    abstract InvocationContext runMethod(InvocationContext c) throws IOException; 
 251.118 -}
   252.1 --- a/rt/launcher/src/main/java/org/apidesign/bck2brwsr/launcher/impl/Console.java	Wed Feb 27 17:50:47 2013 +0100
   252.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   252.3 @@ -1,255 +0,0 @@
   252.4 -/**
   252.5 - * Back 2 Browser Bytecode Translator
   252.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   252.7 - *
   252.8 - * This program is free software: you can redistribute it and/or modify
   252.9 - * it under the terms of the GNU General Public License as published by
  252.10 - * the Free Software Foundation, version 2 of the License.
  252.11 - *
  252.12 - * This program is distributed in the hope that it will be useful,
  252.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  252.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  252.15 - * GNU General Public License for more details.
  252.16 - *
  252.17 - * You should have received a copy of the GNU General Public License
  252.18 - * along with this program. Look for COPYING file in the top folder.
  252.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  252.20 - */
  252.21 -package org.apidesign.bck2brwsr.launcher.impl;
  252.22 -
  252.23 -import java.io.IOException;
  252.24 -import java.io.InputStream;
  252.25 -import java.lang.reflect.InvocationTargetException;
  252.26 -import java.lang.reflect.Method;
  252.27 -import java.lang.reflect.Modifier;
  252.28 -import java.net.URL;
  252.29 -import java.util.Enumeration;
  252.30 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  252.31 -
  252.32 -/**
  252.33 - *
  252.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  252.35 - */
  252.36 -public class Console {
  252.37 -    private Console() {
  252.38 -    }
  252.39 -    static {
  252.40 -        turnAssetionStatusOn();
  252.41 -    }
  252.42 -    
  252.43 -    @JavaScriptBody(args = {"id", "attr"}, body = 
  252.44 -        "return window.document.getElementById(id)[attr].toString();")
  252.45 -    private static native Object getAttr(String id, String attr);
  252.46 -
  252.47 -    @JavaScriptBody(args = {"id", "attr", "value"}, body = 
  252.48 -        "window.document.getElementById(id)[attr] = value;")
  252.49 -    private static native void setAttr(String id, String attr, Object value);
  252.50 -    
  252.51 -    @JavaScriptBody(args = {}, body = "return; window.close();")
  252.52 -    private static native void closeWindow();
  252.53 -
  252.54 -    private static void log(String newText) {
  252.55 -        String id = "bck2brwsr.result";
  252.56 -        String attr = "value";
  252.57 -        setAttr(id, attr, getAttr(id, attr) + "\n" + newText);
  252.58 -        setAttr(id, "scrollTop", getAttr(id, "scrollHeight"));
  252.59 -    }
  252.60 -    
  252.61 -    public static void execute() throws Exception {
  252.62 -        String clazz = (String) getAttr("clazz", "value");
  252.63 -        String method = (String) getAttr("method", "value");
  252.64 -        Object res = invokeMethod(clazz, method);
  252.65 -        setAttr("bck2brwsr.result", "value", res);
  252.66 -    }
  252.67 -
  252.68 -    @JavaScriptBody(args = { "url", "callback", "arr" }, body = ""
  252.69 -        + "var request = new XMLHttpRequest();\n"
  252.70 -        + "request.open('GET', url, true);\n"
  252.71 -        + "request.onreadystatechange = function() {\n"
  252.72 -        + "  if (this.readyState!==4) return;\n"
  252.73 -        + "  arr[0] = this.responseText;\n"
  252.74 -        + "  callback.run__V();\n"
  252.75 -        + "};"
  252.76 -        + "request.send();"
  252.77 -    )
  252.78 -    private static native void loadText(String url, Runnable callback, String[] arr) throws IOException;
  252.79 -    
  252.80 -    public static void harness(String url) throws IOException {
  252.81 -        log("Connecting to " + url);
  252.82 -        Request r = new Request(url);
  252.83 -    }
  252.84 -    
  252.85 -    private static class Request implements Runnable {
  252.86 -        private final String[] arr = { null };
  252.87 -        private final String url;
  252.88 -
  252.89 -        private Request(String url) throws IOException {
  252.90 -            this.url = url;
  252.91 -            loadText(url, this, arr);
  252.92 -        }
  252.93 -        
  252.94 -        @Override
  252.95 -        public void run() {
  252.96 -            try {
  252.97 -                String data = arr[0];
  252.98 -                log("\nGot \"" + data + "\"");
  252.99 -                
 252.100 -                if (data == null) {
 252.101 -                    log("Some error exiting");
 252.102 -                    closeWindow();
 252.103 -                    return;
 252.104 -                }
 252.105 -                
 252.106 -                if (data.isEmpty()) {
 252.107 -                    log("No data, exiting");
 252.108 -                    closeWindow();
 252.109 -                    return;
 252.110 -                }
 252.111 -                
 252.112 -                Case c = Case.parseData(data);
 252.113 -                if (c.getHtmlFragment() != null) {
 252.114 -                    setAttr("bck2brwsr.fragment", "innerHTML", c.getHtmlFragment());
 252.115 -                }
 252.116 -                log("Invoking " + c.getClassName() + '.' + c.getMethodName() + " as request: " + c.getRequestId());
 252.117 -
 252.118 -                Object result = invokeMethod(c.getClassName(), c.getMethodName());
 252.119 -                
 252.120 -                setAttr("bck2brwsr.fragment", "innerHTML", "");
 252.121 -                log("Result: " + result);
 252.122 -                
 252.123 -                result = encodeURL("" + result);
 252.124 -                
 252.125 -                log("Sending back: " + url + "?request=" + c.getRequestId() + "&result=" + result);
 252.126 -                String u = url + "?request=" + c.getRequestId() + "&result=" + result;
 252.127 -                
 252.128 -                loadText(u, this, arr);
 252.129 -                
 252.130 -            } catch (Exception ex) {
 252.131 -                log(ex.getClass().getName() + ":" + ex.getMessage());
 252.132 -            }
 252.133 -        }
 252.134 -    }
 252.135 -    
 252.136 -    private static String encodeURL(String r) {
 252.137 -        StringBuilder sb = new StringBuilder();
 252.138 -        for (int i = 0; i < r.length(); i++) {
 252.139 -            int ch = r.charAt(i);
 252.140 -            if (ch < 32 || ch == '%' || ch == '+') {
 252.141 -                sb.append("%").append(("0" + Integer.toHexString(ch)).substring(0, 2));
 252.142 -            } else {
 252.143 -                if (ch == 32) {
 252.144 -                    sb.append("+");
 252.145 -                } else {
 252.146 -                    sb.append((char)ch);
 252.147 -                }
 252.148 -            }
 252.149 -        }
 252.150 -        return sb.toString();
 252.151 -    }
 252.152 -    
 252.153 -    static String invoke(String clazz, String method) throws ClassNotFoundException, InvocationTargetException, IllegalAccessException, InstantiationException {
 252.154 -        final Object r = invokeMethod(clazz, method);
 252.155 -        return r == null ? "null" : r.toString().toString();
 252.156 -    }
 252.157 -
 252.158 -    /** Helper method that inspects the classpath and loads given resource
 252.159 -     * (usually a class file). Used while running tests in Rhino.
 252.160 -     * 
 252.161 -     * @param name resource name to find
 252.162 -     * @return the array of bytes in the given resource
 252.163 -     * @throws IOException I/O in case something goes wrong
 252.164 -     */
 252.165 -    public static byte[] read(String name) throws IOException {
 252.166 -        URL u = null;
 252.167 -        Enumeration<URL> en = Console.class.getClassLoader().getResources(name);
 252.168 -        while (en.hasMoreElements()) {
 252.169 -            u = en.nextElement();
 252.170 -        }
 252.171 -        if (u == null) {
 252.172 -            throw new IOException("Can't find " + name);
 252.173 -        }
 252.174 -        try (InputStream is = u.openStream()) {
 252.175 -            byte[] arr;
 252.176 -            arr = new byte[is.available()];
 252.177 -            int offset = 0;
 252.178 -            while (offset < arr.length) {
 252.179 -                int len = is.read(arr, offset, arr.length - offset);
 252.180 -                if (len == -1) {
 252.181 -                    throw new IOException("Can't read " + name);
 252.182 -                }
 252.183 -                offset += len;
 252.184 -            }
 252.185 -            return arr;
 252.186 -        }
 252.187 -    }
 252.188 -   
 252.189 -    private static Object invokeMethod(String clazz, String method) 
 252.190 -    throws ClassNotFoundException, InvocationTargetException, 
 252.191 -    SecurityException, IllegalAccessException, IllegalArgumentException,
 252.192 -    InstantiationException {
 252.193 -        Method found = null;
 252.194 -        Class<?> c = Class.forName(clazz);
 252.195 -        for (Method m : c.getMethods()) {
 252.196 -            if (m.getName().equals(method)) {
 252.197 -                found = m;
 252.198 -            }
 252.199 -        }
 252.200 -        Object res;
 252.201 -        if (found != null) {
 252.202 -            try {
 252.203 -                if ((found.getModifiers() & Modifier.STATIC) != 0) {
 252.204 -                    res = found.invoke(null);
 252.205 -                } else {
 252.206 -                    res = found.invoke(c.newInstance());
 252.207 -                }
 252.208 -            } catch (Throwable ex) {
 252.209 -                res = ex.getClass().getName() + ":" + ex.getMessage();
 252.210 -            }
 252.211 -        } else {
 252.212 -            res = "Can't find method " + method + " in " + clazz;
 252.213 -        }
 252.214 -        return res;
 252.215 -    }
 252.216 -
 252.217 -    @JavaScriptBody(args = {}, body = "vm.desiredAssertionStatus = true;")
 252.218 -    private static void turnAssetionStatusOn() {
 252.219 -    }
 252.220 -    
 252.221 -    private static final class Case {
 252.222 -        private final Object data;
 252.223 -
 252.224 -        private Case(Object data) {
 252.225 -            this.data = data;
 252.226 -        }
 252.227 -        
 252.228 -        public static Case parseData(String s) {
 252.229 -            return new Case(toJSON(s));
 252.230 -        }
 252.231 -        
 252.232 -        public String getMethodName() {
 252.233 -            return value("methodName", data);
 252.234 -        }
 252.235 -
 252.236 -        public String getClassName() {
 252.237 -            return value("className", data);
 252.238 -        }
 252.239 -        
 252.240 -        public String getRequestId() {
 252.241 -            return value("request", data);
 252.242 -        }
 252.243 -
 252.244 -        public String getHtmlFragment() {
 252.245 -            return value("html", data);
 252.246 -        }
 252.247 -        
 252.248 -        @JavaScriptBody(args = "s", body = "return eval('(' + s + ')');")
 252.249 -        private static native Object toJSON(String s);
 252.250 -        
 252.251 -        @JavaScriptBody(args = {"p", "d"}, body = 
 252.252 -              "var v = d[p];\n"
 252.253 -            + "if (typeof v === 'undefined') return null;\n"
 252.254 -            + "return v.toString();"
 252.255 -        )
 252.256 -        private static native String value(String p, Object d);
 252.257 -    }
 252.258 -}
   253.1 --- a/rt/launcher/src/main/resources/org/apidesign/bck2brwsr/launcher/harness.xhtml	Wed Feb 27 17:50:47 2013 +0100
   253.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   253.3 @@ -1,43 +0,0 @@
   253.4 -<?xml version="1.0" encoding="UTF-8"?>
   253.5 -<!--
   253.6 -
   253.7 -    Back 2 Browser Bytecode Translator
   253.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   253.9 -
  253.10 -    This program is free software: you can redistribute it and/or modify
  253.11 -    it under the terms of the GNU General Public License as published by
  253.12 -    the Free Software Foundation, version 2 of the License.
  253.13 -
  253.14 -    This program is distributed in the hope that it will be useful,
  253.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  253.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  253.17 -    GNU General Public License for more details.
  253.18 -
  253.19 -    You should have received a copy of the GNU General Public License
  253.20 -    along with this program. Look for COPYING file in the top folder.
  253.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
  253.22 -
  253.23 --->
  253.24 -<!DOCTYPE html>
  253.25 -<html xmlns="http://www.w3.org/1999/xhtml">
  253.26 -    <head>
  253.27 -        <title>Bck2Brwsr Harness</title>
  253.28 -    </head>
  253.29 -    <body>
  253.30 -        <script src="/bck2brwsr.js"></script>
  253.31 -        <script>
  253.32 -            var vm = bck2brwsr();
  253.33 -        </script>
  253.34 -        
  253.35 -        <h1>Bck2Brwsr Execution Harness</h1>
  253.36 -        
  253.37 -        <textarea id="bck2brwsr.result" rows="25" style="width: 100%;" disabled="">
  253.38 -        </textarea>
  253.39 -
  253.40 -        <div id="bck2brwsr.fragment"/>
  253.41 -        
  253.42 -        <script type="text/javascript">
  253.43 -            vm.loadClass('org.apidesign.bck2brwsr.launcher.impl.Console').harness__VLjava_lang_String_2('$U/../data');
  253.44 -        </script>
  253.45 -    </body>
  253.46 -</html>
   254.1 --- a/rt/mojo/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   254.2 +++ b/rt/mojo/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   254.3 @@ -1,18 +1,17 @@
   254.4  <?xml version="1.0"?>
   254.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   254.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   254.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   254.8    <modelVersion>4.0.0</modelVersion>
   254.9    <parent>
  254.10      <groupId>org.apidesign.bck2brwsr</groupId>
  254.11      <artifactId>rt</artifactId>
  254.12 -    <version>0.3-SNAPSHOT</version>
  254.13 +    <version>0.9-SNAPSHOT</version>
  254.14    </parent>
  254.15    <groupId>org.apidesign.bck2brwsr</groupId>
  254.16 -  <artifactId>mojo</artifactId>
  254.17 -  <version>0.3-SNAPSHOT</version>
  254.18 +  <artifactId>bck2brwsr-maven-plugin</artifactId>
  254.19 +  <version>0.9-SNAPSHOT</version>
  254.20    <packaging>maven-plugin</packaging>
  254.21 -  <name>Bck2Brwsr Maven Project</name>
  254.22 -  <url>http://maven.apache.org</url>
  254.23 +  <name>Bck2Brwsr Maven Plugin</name>
  254.24 +  <url>http://bck2brwsr.apidesign.org/</url>
  254.25        <build>
  254.26          <plugins>
  254.27              <plugin>
  254.28 @@ -63,7 +62,7 @@
  254.29      <dependency>
  254.30        <groupId>${project.groupId}</groupId>
  254.31        <artifactId>vm4brwsr</artifactId>
  254.32 -      <version>0.3-SNAPSHOT</version>
  254.33 +      <version>${project.version}</version>
  254.34        <exclusions>
  254.35          <exclusion>
  254.36            <artifactId>emul.mini</artifactId>
  254.37 @@ -82,5 +81,15 @@
  254.38          <artifactId>launcher</artifactId>
  254.39        <version>${project.version}</version>
  254.40      </dependency>
  254.41 +    <dependency>
  254.42 +        <groupId>${project.groupId}</groupId>
  254.43 +        <artifactId>launcher.http</artifactId>
  254.44 +      <version>${project.version}</version>
  254.45 +    </dependency>
  254.46 +    <dependency>
  254.47 +        <groupId>${project.groupId}</groupId>
  254.48 +        <artifactId>launcher.fx</artifactId>
  254.49 +      <version>${project.version}</version>
  254.50 +    </dependency>
  254.51  </dependencies>
  254.52  </project>
   255.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrswrMojo.java	Wed Feb 27 17:50:47 2013 +0100
   255.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   255.3 @@ -1,99 +0,0 @@
   255.4 -/**
   255.5 - * Back 2 Browser Bytecode Translator
   255.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   255.7 - *
   255.8 - * This program is free software: you can redistribute it and/or modify
   255.9 - * it under the terms of the GNU General Public License as published by
  255.10 - * the Free Software Foundation, version 2 of the License.
  255.11 - *
  255.12 - * This program is distributed in the hope that it will be useful,
  255.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  255.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  255.15 - * GNU General Public License for more details.
  255.16 - *
  255.17 - * You should have received a copy of the GNU General Public License
  255.18 - * along with this program. Look for COPYING file in the top folder.
  255.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  255.20 - */
  255.21 -package org.apidesign.bck2brwsr.mojo;
  255.22 -
  255.23 -import java.io.Closeable;
  255.24 -import org.apache.maven.plugin.AbstractMojo;
  255.25 -
  255.26 -import java.io.File;
  255.27 -import java.io.IOException;
  255.28 -import java.net.MalformedURLException;
  255.29 -import java.net.URL;
  255.30 -import java.net.URLClassLoader;
  255.31 -import java.util.ArrayList;
  255.32 -import java.util.Collection;
  255.33 -import java.util.List;
  255.34 -import org.apache.maven.artifact.Artifact;
  255.35 -import org.apache.maven.plugin.MojoExecutionException;
  255.36 -import org.apache.maven.plugins.annotations.LifecyclePhase;
  255.37 -import org.apache.maven.plugins.annotations.Mojo;
  255.38 -import org.apache.maven.plugins.annotations.Parameter;
  255.39 -import org.apache.maven.project.MavenProject;
  255.40 -import org.apidesign.bck2brwsr.launcher.Launcher;
  255.41 -
  255.42 -/** Executes given HTML page in a browser. */
  255.43 -@Mojo(name="brwsr", defaultPhase=LifecyclePhase.NONE)
  255.44 -public class BrswrMojo extends AbstractMojo {
  255.45 -    public BrswrMojo() {
  255.46 -    }
  255.47 -    /** Resource to show as initial page */
  255.48 -    @Parameter
  255.49 -    private String startpage;
  255.50 -
  255.51 -    @Parameter(defaultValue="${project}")
  255.52 -    private MavenProject prj;
  255.53 -    
  255.54 -    /** Root of the class files */
  255.55 -    @Parameter(defaultValue="${project.build.directory}/classes")
  255.56 -    private File classes;
  255.57 -    
  255.58 -    /** Root of all pages, and files, etc. */
  255.59 -    @Parameter
  255.60 -    private File directory;
  255.61 -
  255.62 -    @Override
  255.63 -    public void execute() throws MojoExecutionException {
  255.64 -        if (startpage == null) {
  255.65 -            throw new MojoExecutionException("You have to provide a start page");
  255.66 -        }
  255.67 -        
  255.68 -        try {
  255.69 -            Closeable httpServer;
  255.70 -            if (directory != null) {
  255.71 -                httpServer = Launcher.showDir(directory, startpage);
  255.72 -            } else {
  255.73 -                URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
  255.74 -                try {
  255.75 -                    httpServer = Launcher.showURL(url, startpage());
  255.76 -                } catch (Exception ex) {
  255.77 -                    throw new MojoExecutionException("Can't open " + startpage(), ex);
  255.78 -                }
  255.79 -            }
  255.80 -            System.in.read();
  255.81 -            httpServer.close();
  255.82 -        } catch (IOException ex) {
  255.83 -            throw new MojoExecutionException("Can't show the browser", ex);
  255.84 -        }
  255.85 -    }
  255.86 -    
  255.87 -    private String startpage() {
  255.88 -        return startpage;
  255.89 -    }
  255.90 -
  255.91 -    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
  255.92 -        List<URL> arr = new ArrayList<URL>();
  255.93 -        arr.add(root.toURI().toURL());
  255.94 -        for (Artifact a : deps) {
  255.95 -            final File f = a.getFile();
  255.96 -            if (f != null) {
  255.97 -                arr.add(f.toURI().toURL());
  255.98 -            }
  255.99 -        }
 255.100 -        return new URLClassLoader(arr.toArray(new URL[0]), BrswrMojo.class.getClassLoader());
 255.101 -    }
 255.102 -}
   256.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   256.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/BrwsrMojo.java	Mon Oct 07 14:20:58 2013 +0200
   256.3 @@ -0,0 +1,121 @@
   256.4 +/**
   256.5 + * Back 2 Browser Bytecode Translator
   256.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   256.7 + *
   256.8 + * This program is free software: you can redistribute it and/or modify
   256.9 + * it under the terms of the GNU General Public License as published by
  256.10 + * the Free Software Foundation, version 2 of the License.
  256.11 + *
  256.12 + * This program is distributed in the hope that it will be useful,
  256.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  256.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  256.15 + * GNU General Public License for more details.
  256.16 + *
  256.17 + * You should have received a copy of the GNU General Public License
  256.18 + * along with this program. Look for COPYING file in the top folder.
  256.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  256.20 + */
  256.21 +package org.apidesign.bck2brwsr.mojo;
  256.22 +
  256.23 +import java.io.Closeable;
  256.24 +import org.apache.maven.plugin.AbstractMojo;
  256.25 +
  256.26 +import java.io.File;
  256.27 +import java.io.IOException;
  256.28 +import java.net.MalformedURLException;
  256.29 +import java.net.URL;
  256.30 +import java.net.URLClassLoader;
  256.31 +import java.util.ArrayList;
  256.32 +import java.util.Collection;
  256.33 +import java.util.List;
  256.34 +import org.apache.maven.artifact.Artifact;
  256.35 +import org.apache.maven.model.Resource;
  256.36 +import org.apache.maven.plugin.MojoExecutionException;
  256.37 +import org.apache.maven.plugins.annotations.LifecyclePhase;
  256.38 +import org.apache.maven.plugins.annotations.Mojo;
  256.39 +import org.apache.maven.plugins.annotations.Parameter;
  256.40 +import org.apache.maven.plugins.annotations.ResolutionScope;
  256.41 +import org.apache.maven.project.MavenProject;
  256.42 +import org.apidesign.bck2brwsr.launcher.Launcher;
  256.43 +
  256.44 +/** Executes given HTML page in a browser. */
  256.45 +@Mojo(
  256.46 +    name="brwsr",
  256.47 +    requiresDependencyResolution = ResolutionScope.RUNTIME,
  256.48 +    defaultPhase=LifecyclePhase.NONE
  256.49 +)
  256.50 +public class BrwsrMojo extends AbstractMojo {
  256.51 +    public BrwsrMojo() {
  256.52 +    }
  256.53 +    
  256.54 +    /** The identification of a launcher to use. Known values <code>fxbrwsr</code>, 
  256.55 +     * <code>bck2brwsr</code>, or 
  256.56 +     * name of an external process to execute.
  256.57 +     */
  256.58 +    @Parameter
  256.59 +    private String launcher;
  256.60 +    
  256.61 +    
  256.62 +    /** Resource to show as initial page */
  256.63 +    @Parameter
  256.64 +    private String startpage;
  256.65 +
  256.66 +    @Parameter(defaultValue="${project}")
  256.67 +    private MavenProject prj;
  256.68 +    
  256.69 +    /** Root of the class files */
  256.70 +    @Parameter(defaultValue="${project.build.directory}/classes")
  256.71 +    private File classes;
  256.72 +    
  256.73 +    /** Root of all pages, and files, etc. */
  256.74 +    @Parameter
  256.75 +    private File directory;
  256.76 +
  256.77 +    @Override
  256.78 +    public void execute() throws MojoExecutionException {
  256.79 +        if (startpage == null) {
  256.80 +            throw new MojoExecutionException("You have to provide a start page");
  256.81 +        }
  256.82 +        try {
  256.83 +            Closeable httpServer;
  256.84 +            if (directory != null) {
  256.85 +                URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  256.86 +                httpServer = Launcher.showDir(launcher, directory, url, startpage);
  256.87 +            } else {
  256.88 +                URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  256.89 +                try {
  256.90 +                    for (Resource r : prj.getResources()) {
  256.91 +                        File f = new File(r.getDirectory(), startpage().replace('/', File.separatorChar));
  256.92 +                        if (f.exists()) {
  256.93 +                            System.setProperty("startpage.file", f.getPath());
  256.94 +                        }
  256.95 +                    }
  256.96 +                    
  256.97 +                    httpServer = Launcher.showURL(launcher, url, startpage());
  256.98 +                } catch (Exception ex) {
  256.99 +                    throw new MojoExecutionException("Can't open " + startpage(), ex);
 256.100 +                }
 256.101 +            }
 256.102 +            System.in.read();
 256.103 +            httpServer.close();
 256.104 +        } catch (IOException ex) {
 256.105 +            throw new MojoExecutionException("Can't show the browser", ex);
 256.106 +        }
 256.107 +    }
 256.108 +    
 256.109 +    private String startpage() {
 256.110 +        return startpage;
 256.111 +    }
 256.112 +
 256.113 +    private static URLClassLoader buildClassLoader(File root, Collection<Artifact> deps) throws MalformedURLException {
 256.114 +        List<URL> arr = new ArrayList<URL>();
 256.115 +        arr.add(root.toURI().toURL());
 256.116 +        for (Artifact a : deps) {
 256.117 +            final File f = a.getFile();
 256.118 +            if (f != null) {
 256.119 +                arr.add(f.toURI().toURL());
 256.120 +            }
 256.121 +        }
 256.122 +        return new URLClassLoader(arr.toArray(new URL[0]), BrwsrMojo.class.getClassLoader());
 256.123 +    }
 256.124 +}
   257.1 --- a/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java	Wed Feb 27 17:50:47 2013 +0100
   257.2 +++ b/rt/mojo/src/main/java/org/apidesign/bck2brwsr/mojo/Java2JavaScript.java	Mon Oct 07 14:20:58 2013 +0200
   257.3 @@ -33,26 +33,43 @@
   257.4  import org.apache.maven.plugins.annotations.LifecyclePhase;
   257.5  import org.apache.maven.plugins.annotations.Mojo;
   257.6  import org.apache.maven.plugins.annotations.Parameter;
   257.7 +import org.apache.maven.plugins.annotations.ResolutionScope;
   257.8  import org.apache.maven.project.MavenProject;
   257.9  import org.apidesign.vm4brwsr.Bck2Brwsr;
  257.10 +import org.apidesign.vm4brwsr.ObfuscationLevel;
  257.11  
  257.12  /** Compiles classes into JavaScript. */
  257.13 -@Mojo(name="j2js", defaultPhase=LifecyclePhase.PROCESS_CLASSES)
  257.14 +@Mojo(name="j2js", 
  257.15 +    requiresDependencyResolution = ResolutionScope.COMPILE,
  257.16 +    defaultPhase=LifecyclePhase.PROCESS_CLASSES
  257.17 +)
  257.18  public class Java2JavaScript extends AbstractMojo {
  257.19      public Java2JavaScript() {
  257.20      }
  257.21      /** Root of the class files */
  257.22      @Parameter(defaultValue="${project.build.directory}/classes")
  257.23      private File classes;
  257.24 -    /** File to generate. Defaults bootjava.js in the first non-empty 
  257.25 -     package under the classes directory */
  257.26 +    /** JavaScript file to generate */
  257.27      @Parameter
  257.28      private File javascript;
  257.29 +
  257.30 +    /** Additional classes that should be pre-compiled into the javascript 
  257.31 +     * file. By default compiles all classes found under <code>classes</code>
  257.32 +     * directory and their transitive closure.
  257.33 +     */
  257.34 +    @Parameter
  257.35 +    private List<String> compileclasses;
  257.36      
  257.37      @Parameter(defaultValue="${project}")
  257.38      private MavenProject prj;
  257.39 -    
  257.40 -    
  257.41 +
  257.42 +    /**
  257.43 +     * The obfuscation level for the generated JavaScript file.
  257.44 +     *
  257.45 +     * @since 0.5
  257.46 +     */
  257.47 +    @Parameter(defaultValue="NONE")
  257.48 +    private ObfuscationLevel obfuscation;
  257.49  
  257.50      @Override
  257.51      public void execute() throws MojoExecutionException {
  257.52 @@ -60,38 +77,32 @@
  257.53              throw new MojoExecutionException("Can't find " + classes);
  257.54          }
  257.55  
  257.56 -        if (javascript == null) {
  257.57 -            javascript = new File(findNonEmptyFolder(classes), "bootjava.js");
  257.58 -        }
  257.59 -
  257.60          List<String> arr = new ArrayList<String>();
  257.61          long newest = collectAllClasses("", classes, arr);
  257.62          
  257.63 +        if (compileclasses != null) {
  257.64 +            arr.retainAll(compileclasses);
  257.65 +            arr.addAll(compileclasses);
  257.66 +        }
  257.67 +        
  257.68          if (javascript.lastModified() > newest) {
  257.69              return;
  257.70          }
  257.71  
  257.72          try {
  257.73 -            URLClassLoader url = buildClassLoader(classes, prj.getDependencyArtifacts());
  257.74 +            URLClassLoader url = buildClassLoader(classes, prj.getArtifacts());
  257.75              FileWriter w = new FileWriter(javascript);
  257.76 -            Bck2Brwsr.generate(w, url, arr.toArray(new String[0]));
  257.77 +            Bck2Brwsr.newCompiler().
  257.78 +                obfuscation(obfuscation).
  257.79 +                resources(url).
  257.80 +                addRootClasses(arr.toArray(new String[0])).
  257.81 +                generate(w);
  257.82              w.close();
  257.83          } catch (IOException ex) {
  257.84              throw new MojoExecutionException("Can't compile", ex);
  257.85          }
  257.86      }
  257.87  
  257.88 -    private static File findNonEmptyFolder(File dir) throws MojoExecutionException {
  257.89 -        if (!dir.isDirectory()) {
  257.90 -            throw new MojoExecutionException("Not a directory " + dir);
  257.91 -        }
  257.92 -        File[] arr = dir.listFiles();
  257.93 -        if (arr.length == 1 && arr[0].isDirectory()) {
  257.94 -            return findNonEmptyFolder(arr[0]);
  257.95 -        }
  257.96 -        return dir;
  257.97 -    }
  257.98 -
  257.99      private static long collectAllClasses(String prefix, File toCheck, List<String> arr) {
 257.100          File[] files = toCheck.listFiles();
 257.101          if (files != null) {
 257.102 @@ -104,7 +115,8 @@
 257.103              }
 257.104              return newest;
 257.105          } else if (toCheck.getName().endsWith(".class")) {
 257.106 -            arr.add(prefix.substring(0, prefix.length() - 7));
 257.107 +            final String cls = prefix.substring(0, prefix.length() - 7);
 257.108 +            arr.add(cls);
 257.109              return toCheck.lastModified();
 257.110          } else {
 257.111              return 0L;
 257.112 @@ -115,7 +127,9 @@
 257.113          List<URL> arr = new ArrayList<URL>();
 257.114          arr.add(root.toURI().toURL());
 257.115          for (Artifact a : deps) {
 257.116 -            arr.add(a.getFile().toURI().toURL());
 257.117 +            if (a.getFile() != null) {
 257.118 +                arr.add(a.getFile().toURI().toURL());
 257.119 +            }
 257.120          }
 257.121          return new URLClassLoader(arr.toArray(new URL[0]), Java2JavaScript.class.getClassLoader());
 257.122      }
   258.1 --- a/rt/mojo/src/main/resources/META-INF/maven/archetype-metadata.xml	Wed Feb 27 17:50:47 2013 +0100
   258.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   258.3 @@ -1,55 +0,0 @@
   258.4 -<?xml version="1.0" encoding="UTF-8"?>
   258.5 -<!--
   258.6 -
   258.7 -    Back 2 Browser Bytecode Translator
   258.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   258.9 -
  258.10 -    This program is free software: you can redistribute it and/or modify
  258.11 -    it under the terms of the GNU General Public License as published by
  258.12 -    the Free Software Foundation, version 2 of the License.
  258.13 -
  258.14 -    This program is distributed in the hope that it will be useful,
  258.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  258.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  258.17 -    GNU General Public License for more details.
  258.18 -
  258.19 -    You should have received a copy of the GNU General Public License
  258.20 -    along with this program. Look for COPYING file in the top folder.
  258.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
  258.22 -
  258.23 --->
  258.24 -<archetype-descriptor name="bck2brwsr">
  258.25 -  <fileSets>
  258.26 -    <fileSet filtered="true" packaged="true">
  258.27 -      <directory>src/main/java</directory>
  258.28 -      <includes>
  258.29 -        <include>**/App.java</include>
  258.30 -      </includes>
  258.31 -    </fileSet>
  258.32 -    <fileSet filtered="true" packaged="true">
  258.33 -      <directory>src/main/resources</directory>
  258.34 -      <includes>
  258.35 -        <include>**/*.xhtml</include>
  258.36 -        <include>**/*.html</include>
  258.37 -      </includes>
  258.38 -    </fileSet>
  258.39 -    <fileSet filtered="true" packaged="true">
  258.40 -      <directory>src/test/java</directory>
  258.41 -      <includes>
  258.42 -        <include>**/*Test.java</include>
  258.43 -      </includes>
  258.44 -    </fileSet>
  258.45 -    <fileSet filtered="false" packaged="false">
  258.46 -      <directory></directory>
  258.47 -      <includes>
  258.48 -        <include>nbactions.xml</include>
  258.49 -      </includes>
  258.50 -    </fileSet>
  258.51 -    <fileSet filtered="true" packaged="false">
  258.52 -      <directory></directory>
  258.53 -      <includes>
  258.54 -        <include>bck2brwsr-assembly.xml</include>
  258.55 -      </includes>
  258.56 -    </fileSet>
  258.57 -  </fileSets>    
  258.58 -</archetype-descriptor>
  258.59 \ No newline at end of file
   259.1 --- a/rt/mojo/src/main/resources/archetype-resources/bck2brwsr-assembly.xml	Wed Feb 27 17:50:47 2013 +0100
   259.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   259.3 @@ -1,61 +0,0 @@
   259.4 -<?xml version="1.0"?>
   259.5 -<!--
   259.6 -
   259.7 -    Back 2 Browser Bytecode Translator
   259.8 -    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   259.9 -
  259.10 -    This program is free software: you can redistribute it and/or modify
  259.11 -    it under the terms of the GNU General Public License as published by
  259.12 -    the Free Software Foundation, version 2 of the License.
  259.13 -
  259.14 -    This program is distributed in the hope that it will be useful,
  259.15 -    but WITHOUT ANY WARRANTY; without even the implied warranty of
  259.16 -    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  259.17 -    GNU General Public License for more details.
  259.18 -
  259.19 -    You should have received a copy of the GNU General Public License
  259.20 -    along with this program. Look for COPYING file in the top folder.
  259.21 -    If not, see http://opensource.org/licenses/GPL-2.0.
  259.22 -
  259.23 --->
  259.24 -<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  259.25 -  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
  259.26 -  
  259.27 -  <id>bck2brwsr</id>
  259.28 -  <formats>
  259.29 -      <format>zip</format>
  259.30 -  </formats>
  259.31 -  <baseDirectory>public_html</baseDirectory>
  259.32 -  <dependencySets>
  259.33 -    <dependencySet>
  259.34 -        <useProjectArtifact>false</useProjectArtifact>
  259.35 -        <scope>runtime</scope>
  259.36 -        <outputDirectory>lib</outputDirectory>
  259.37 -        <includes>
  259.38 -            <include>*:jar</include>
  259.39 -            <include>*:rt</include>
  259.40 -        </includes>
  259.41 -    </dependencySet>
  259.42 -    <dependencySet>
  259.43 -        <useProjectArtifact>false</useProjectArtifact>
  259.44 -        <scope>provided</scope>
  259.45 -        <includes>
  259.46 -            <include>*:js</include>
  259.47 -        </includes>
  259.48 -        <unpack>true</unpack>
  259.49 -        <outputDirectory>/</outputDirectory>
  259.50 -    </dependencySet>
  259.51 -  </dependencySets> 
  259.52 -  <files>
  259.53 -    <file>
  259.54 -      <source>${project.build.directory}/${project.build.finalName}.jar</source>
  259.55 -      <outputDirectory>/</outputDirectory>
  259.56 -    </file>
  259.57 -    <file>
  259.58 -      <source>${project.build.directory}/classes/${package.replace('.','/')}/index.html</source>
  259.59 -      <outputDirectory>/</outputDirectory>
  259.60 -      <destName>index.html</destName>
  259.61 -    </file>
  259.62 -  </files>
  259.63 -
  259.64 -</assembly>
  259.65 \ No newline at end of file
   260.1 --- a/rt/mojo/src/main/resources/archetype-resources/nbactions.xml	Wed Feb 27 17:50:47 2013 +0100
   260.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   260.3 @@ -1,10 +0,0 @@
   260.4 -<?xml version="1.0" encoding="UTF-8"?>
   260.5 -<actions>
   260.6 -    <action>
   260.7 -        <actionName>run</actionName>
   260.8 -        <goals>
   260.9 -            <goal>process-classes</goal>
  260.10 -            <goal>org.apidesign.bck2brwsr:mojo:0.3-SNAPSHOT:brwsr</goal>
  260.11 -        </goals>
  260.12 -    </action>
  260.13 -</actions>
   261.1 --- a/rt/mojo/src/main/resources/archetype-resources/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   261.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   261.3 @@ -1,135 +0,0 @@
   261.4 -<?xml version="1.0"?>
   261.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   261.6 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   261.7 -  <modelVersion>4.0.0</modelVersion>
   261.8 -
   261.9 -  <groupId>${groupId}</groupId>
  261.10 -  <artifactId>${artifactId}</artifactId>
  261.11 -  <version>${version}</version>
  261.12 -  <packaging>jar</packaging>
  261.13 -
  261.14 -  <name>${artifactId}</name>
  261.15 -
  261.16 -  <repositories>
  261.17 -      <repository>
  261.18 -          <id>java.net</id>
  261.19 -          <name>Java.net</name>
  261.20 -          <url>https://maven.java.net/content/repositories/snapshots/</url>
  261.21 -          <snapshots>
  261.22 -              <enabled>true</enabled>
  261.23 -          </snapshots>
  261.24 -      </repository>
  261.25 -      <repository>
  261.26 -          <id>netbeans</id>
  261.27 -          <name>NetBeans</name>
  261.28 -          <url>http://bits.netbeans.org/maven2/</url>
  261.29 -      </repository>
  261.30 -  </repositories>
  261.31 -  <pluginRepositories>
  261.32 -      <pluginRepository>
  261.33 -          <id>java.net</id>
  261.34 -          <name>Local Maven repository of releases</name>
  261.35 -          <url>https://maven.java.net/content/repositories/snapshots/</url>
  261.36 -          <snapshots>
  261.37 -              <enabled>true</enabled>
  261.38 -          </snapshots>
  261.39 -      </pluginRepository>
  261.40 -  </pluginRepositories>
  261.41 -
  261.42 -  <properties>
  261.43 -    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  261.44 -  </properties>
  261.45 -  <build>
  261.46 -      <plugins>
  261.47 -            <plugin>
  261.48 -                <groupId>org.apidesign.bck2brwsr</groupId>
  261.49 -                <artifactId>mojo</artifactId>
  261.50 -                <version>0.3-SNAPSHOT</version>
  261.51 -                <executions>
  261.52 -                    <execution>
  261.53 -                        <goals>
  261.54 -                            <goal>brwsr</goal>
  261.55 -                        </goals>
  261.56 -                    </execution>
  261.57 -                </executions>
  261.58 -                <configuration>
  261.59 -                    <startpage>${package.replace('.','/')}/index.html</startpage>
  261.60 -                </configuration>
  261.61 -            </plugin>
  261.62 -         <plugin>
  261.63 -            <groupId>org.apache.maven.plugins</groupId>
  261.64 -            <artifactId>maven-compiler-plugin</artifactId>
  261.65 -            <version>2.3.2</version>
  261.66 -            <configuration>
  261.67 -               <source>1.7</source>
  261.68 -               <target>1.7</target>
  261.69 -            </configuration>
  261.70 -         </plugin>
  261.71 -         <plugin>
  261.72 -             <groupId>org.apache.maven.plugins</groupId>
  261.73 -             <artifactId>maven-jar-plugin</artifactId>
  261.74 -             <version>2.4</version>
  261.75 -             <configuration>
  261.76 -                 <archive>
  261.77 -                     <manifest>
  261.78 -                         <addClasspath>true</addClasspath>
  261.79 -                         <classpathPrefix>lib/</classpathPrefix>
  261.80 -                     </manifest>
  261.81 -                 </archive>
  261.82 -             </configuration>
  261.83 -         </plugin>
  261.84 -         <plugin>
  261.85 -             <artifactId>maven-assembly-plugin</artifactId>
  261.86 -             <version>2.4</version>
  261.87 -             <executions>
  261.88 -                 <execution>
  261.89 -                     <id>distro-assembly</id>
  261.90 -                     <phase>package</phase>
  261.91 -                     <goals>
  261.92 -                         <goal>single</goal>
  261.93 -                     </goals>
  261.94 -                     <configuration>
  261.95 -                         <descriptors>
  261.96 -                             <descriptor>bck2brwsr-assembly.xml</descriptor>
  261.97 -                         </descriptors>
  261.98 -                     </configuration>
  261.99 -                 </execution>
 261.100 -             </executions>                
 261.101 -         </plugin>      
 261.102 -      </plugins>
 261.103 -  </build>
 261.104 -
 261.105 -  <dependencies>
 261.106 -    <dependency>
 261.107 -      <groupId>org.apidesign.bck2brwsr</groupId>
 261.108 -      <artifactId>emul</artifactId>
 261.109 -      <version>0.3-SNAPSHOT</version>
 261.110 -      <classifier>rt</classifier>
 261.111 -    </dependency>
 261.112 -    <dependency>
 261.113 -      <groupId>org.apidesign.bck2brwsr</groupId>
 261.114 -      <artifactId>javaquery.api</artifactId>
 261.115 -      <version>0.3-SNAPSHOT</version>
 261.116 -    </dependency>
 261.117 -    <dependency>
 261.118 -      <groupId>org.testng</groupId>
 261.119 -      <artifactId>testng</artifactId>
 261.120 -      <version>6.5.2</version>
 261.121 -      <scope>test</scope>
 261.122 -    </dependency>
 261.123 -    <dependency>
 261.124 -      <groupId>org.apidesign.bck2brwsr</groupId>
 261.125 -      <artifactId>vm4brwsr</artifactId>
 261.126 -      <classifier>js</classifier>
 261.127 -      <type>zip</type>
 261.128 -      <version>0.3-SNAPSHOT</version>
 261.129 -      <scope>provided</scope>
 261.130 -    </dependency>
 261.131 -    <dependency>
 261.132 -      <groupId>org.apidesign.bck2brwsr</groupId>
 261.133 -      <artifactId>vmtest</artifactId>
 261.134 -      <version>0.3-SNAPSHOT</version>
 261.135 -      <scope>test</scope>
 261.136 -    </dependency>
 261.137 -  </dependencies>
 261.138 -</project>
   262.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/java/App.java	Wed Feb 27 17:50:47 2013 +0100
   262.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   262.3 @@ -1,34 +0,0 @@
   262.4 -package ${package};
   262.5 -
   262.6 -import org.apidesign.bck2brwsr.htmlpage.api.*;
   262.7 -import static org.apidesign.bck2brwsr.htmlpage.api.OnEvent.*;
   262.8 -import org.apidesign.bck2brwsr.htmlpage.api.Page;
   262.9 -import org.apidesign.bck2brwsr.htmlpage.api.Property;
  262.10 -import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
  262.11 -
  262.12 -/** Edit the index.xhtml file. Use 'id' to name certain HTML elements.
  262.13 - * Use this class to define behavior of the elements.
  262.14 - */
  262.15 -@Page(xhtml="index.html", className="Index", properties={
  262.16 -    @Property(name="name", type=String.class)
  262.17 -})
  262.18 -public class App {
  262.19 -    static {
  262.20 -        Index model = new Index();
  262.21 -        model.setName("World");
  262.22 -        model.applyBindings();
  262.23 -    }
  262.24 -    
  262.25 -    @On(event = CLICK, id="hello")
  262.26 -    static void hello(Index m) {
  262.27 -        GraphicsContext g = m.CANVAS.getContext();
  262.28 -        g.clearRect(0, 0, 1000, 1000);
  262.29 -        g.setFont("italic 40px Calibri");
  262.30 -        g.fillText(m.getHelloMessage(), 10, 40);
  262.31 -    }
  262.32 -    
  262.33 -    @ComputedProperty
  262.34 -    static String helloMessage(String name) {
  262.35 -        return "Hello " + name + "!";
  262.36 -    }
  262.37 -}
   263.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/main/resources/index.html	Wed Feb 27 17:50:47 2013 +0100
   263.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   263.3 @@ -1,22 +0,0 @@
   263.4 -<?xml version="1.0" encoding="UTF-8"?>
   263.5 -<!DOCTYPE html>
   263.6 -<html xmlns="http://www.w3.org/1999/xhtml">
   263.7 -    <head>
   263.8 -        <title>Bck2Brwsr's Hello World</title>
   263.9 -    </head>
  263.10 -    <body>
  263.11 -        <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
  263.12 -        Your name: <input id='input' data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
  263.13 -        <button id="hello">Say Hello!</button>
  263.14 -        <p>
  263.15 -            <canvas id="canvas" width="300" height="50">
  263.16 -            </canvas>
  263.17 -        </p>
  263.18 -
  263.19 -        <script src="bck2brwsr.js"></script>
  263.20 -        <script type="text/javascript">
  263.21 -            var vm = bck2brwsr('${artifactId}-${version}.jar');
  263.22 -            vm.loadClass('${package}.App');
  263.23 -        </script>
  263.24 -    </body>
  263.25 -</html>
   264.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/AppTest.java	Wed Feb 27 17:50:47 2013 +0100
   264.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   264.3 @@ -1,26 +0,0 @@
   264.4 -package ${package};
   264.5 -
   264.6 -import static org.testng.Assert.*;
   264.7 -import org.testng.annotations.BeforeMethod;
   264.8 -import org.testng.annotations.Test;
   264.9 -
  264.10 -/** Demonstrating POJO testing of HTML page model. Runs in good old HotSpot
  264.11 - * as it does not reference any HTML elements or browser functionality. Just
  264.12 - * operates on the page model.
  264.13 - *
  264.14 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  264.15 - */
  264.16 -public class AppTest {
  264.17 -    private Index model;
  264.18 -    
  264.19 -
  264.20 -    @BeforeMethod
  264.21 -    public void initModel() {
  264.22 -        model = new Index().applyBindings();
  264.23 -    }
  264.24 -
  264.25 -    @Test public void testHelloMessage() {
  264.26 -        model.setName("Joe");
  264.27 -        assertEquals(model.getHelloMessage(), "Hello Joe!", "Cleared after pressing +");
  264.28 -    }
  264.29 -}
   265.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/InconsistencyTest.java	Wed Feb 27 17:50:47 2013 +0100
   265.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   265.3 @@ -1,40 +0,0 @@
   265.4 -package ${package};
   265.5 -
   265.6 -import org.apidesign.bck2brwsr.vmtest.Compare;
   265.7 -import org.apidesign.bck2brwsr.vmtest.VMTest;
   265.8 -import org.testng.annotations.Factory;
   265.9 -
  265.10 -/** Bck2brwsr cares about compatibility with real Java. Whatever API is
  265.11 - * supported by bck2brwsr, it needs to behave the same way as when running
  265.12 - * in HotSpot VM. 
  265.13 - * <p>
  265.14 - * There can be bugs, however. To help us fix them, we kindly ask you to 
  265.15 - * write an "inconsistency" test. A test that compares behavior of the API
  265.16 - * between real VM and bck2brwsr VM. This class is skeleton of such test.
  265.17 - *
  265.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  265.19 - */
  265.20 -public class InconsistencyTest {
  265.21 -    /** A method to demonstrate inconsistency between bck2brwsr and HotSpot.
  265.22 -     * Make calls to an API that behaves strangely, return some result at
  265.23 -     * the end. No need to use any <code>assert</code>.
  265.24 -     * 
  265.25 -     * @return value to compare between HotSpot and bck2brwsr
  265.26 -     */
  265.27 -    @Compare
  265.28 -    public int checkStringHashCode() throws Exception {
  265.29 -        return "Is string hashCode the same?".hashCode();
  265.30 -    }
  265.31 -
  265.32 -    /** Factory method that creates a three tests for each method annotated with
  265.33 -     * {@link org.apidesign.bck2brwsr.vmtest.Compare}. One executes the code in
  265.34 -     * HotSpot, one in Rhino and the last one compares the results.
  265.35 -     * 
  265.36 -     * @see org.apidesign.bck2brwsr.vmtest.VMTest
  265.37 -     */
  265.38 -    @Factory
  265.39 -    public static Object[] create() {
  265.40 -        return VMTest.create(InconsistencyTest.class);
  265.41 -    }
  265.42 -    
  265.43 -}
   266.1 --- a/rt/mojo/src/main/resources/archetype-resources/src/test/java/IntegrationTest.java	Wed Feb 27 17:50:47 2013 +0100
   266.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   266.3 @@ -1,46 +0,0 @@
   266.4 -package ${package};
   266.5 -
   266.6 -import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
   266.7 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
   266.8 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
   266.9 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  266.10 -import org.testng.annotations.Factory;
  266.11 -
  266.12 -/** Sometimes it is useful to run tests inside of the real browser. 
  266.13 - * To do that just annotate your method with {@link org.apidesign.bck2brwsr.vmtest.BrwsrTest}
  266.14 - * and that is it. If your code references elements on the HTML page,
  266.15 - * you can pass in an {@link org.apidesign.bck2brwsr.vmtest.HtmlFragment} which
  266.16 - * will be made available on the page before your test starts.
  266.17 - *
  266.18 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  266.19 - */
  266.20 -public class IntegrationTest {
  266.21 -    
  266.22 -    /** Write to testing code here. Use <code>assert</code> (but not TestNG's
  266.23 -     * Assert, as TestNG is not compiled with target 1.6 yet).
  266.24 -     */
  266.25 -    @HtmlFragment(
  266.26 -        "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
  266.27 -        "Your name: <input id='input' data-bind=\"value: name, valueUpdate: 'afterkeydown'\"></input>\n" +
  266.28 -        "<button id=\"hello\">Say Hello!</button>\n" +
  266.29 -        "<p>\n" +
  266.30 -        "    <canvas id=\"canvas\" width=\"300\" height=\"50\"></canvas>\n" +
  266.31 -        "</p>\n"
  266.32 -    )
  266.33 -    @BrwsrTest
  266.34 -    public void modifyValueAssertChangeInModel() {
  266.35 -        Index m = new Index();
  266.36 -        m.setName("Joe Hacker");
  266.37 -        m.applyBindings();
  266.38 -        assert "Joe Hacker".equals(m.INPUT.getValue()) : "Value is really Joe Hacker: " + m.INPUT.getValue();
  266.39 -        m.INPUT.setValue("Happy Joe");
  266.40 -        m.triggerEvent(m.INPUT, OnEvent.CHANGE);
  266.41 -        assert "Happy Joe".equals(m.getName()) : "Name property updated to Happy Joe: " + m.getName();
  266.42 -    }
  266.43 -
  266.44 -    @Factory
  266.45 -    public static Object[] create() {
  266.46 -        return VMTest.create(IntegrationTest.class);
  266.47 -    }
  266.48 -    
  266.49 -}
   267.1 --- a/rt/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   267.2 +++ b/rt/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   267.3 @@ -3,21 +3,19 @@
   267.4    <modelVersion>4.0.0</modelVersion>
   267.5    <groupId>org.apidesign.bck2brwsr</groupId>
   267.6    <artifactId>rt</artifactId>
   267.7 -  <version>0.3-SNAPSHOT</version>
   267.8 +  <version>0.9-SNAPSHOT</version>
   267.9    <packaging>pom</packaging>
  267.10 -  <name>Bck3Brwsr Runtime</name>
  267.11 +  <name>Bck2Brwsr Runtime</name>
  267.12    <parent>
  267.13      <groupId>org.apidesign</groupId>
  267.14      <artifactId>bck2brwsr</artifactId>
  267.15 -    <version>0.3-SNAPSHOT</version>
  267.16 +    <version>0.9-SNAPSHOT</version>
  267.17    </parent>  
  267.18    <modules>
  267.19      <module>core</module>
  267.20      <module>emul</module>
  267.21 -    <module>javap</module>
  267.22 -    <module>launcher</module>
  267.23      <module>mojo</module>
  267.24      <module>vm</module>
  267.25      <module>vmtest</module>
  267.26    </modules>
  267.27 -</project>
  267.28 \ No newline at end of file
  267.29 +</project>
   268.1 --- a/rt/vm/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   268.2 +++ b/rt/vm/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   268.3 @@ -1,15 +1,14 @@
   268.4 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   268.5 -  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   268.6 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   268.7    <modelVersion>4.0.0</modelVersion>
   268.8    <parent>
   268.9      <groupId>org.apidesign.bck2brwsr</groupId>
  268.10      <artifactId>rt</artifactId>
  268.11 -    <version>0.3-SNAPSHOT</version>
  268.12 +    <version>0.9-SNAPSHOT</version>
  268.13    </parent>
  268.14  
  268.15    <groupId>org.apidesign.bck2brwsr</groupId>
  268.16    <artifactId>vm4brwsr</artifactId>
  268.17 -  <version>0.3-SNAPSHOT</version>
  268.18 +  <version>0.9-SNAPSHOT</version>
  268.19    <packaging>jar</packaging>
  268.20  
  268.21    <name>Virtual Machine for Browser</name>
  268.22 @@ -44,6 +43,7 @@
  268.23    <scm>
  268.24        <connection>scm:hg:http://source.apidesign.org/hg/bck2brwsr</connection>
  268.25        <url>http://source.apidesign.org/hg/bck2brwsr</url>
  268.26 +    <tag>HEAD</tag>
  268.27    </scm>
  268.28    <build>
  268.29        <plugins>
  268.30 @@ -69,6 +69,13 @@
  268.31              </configuration>
  268.32           </plugin>
  268.33           <plugin>
  268.34 +             <groupId>org.apache.maven.plugins</groupId>
  268.35 +             <artifactId>maven-javadoc-plugin</artifactId>
  268.36 +             <configuration>
  268.37 +                 <skip>false</skip>
  268.38 +             </configuration>
  268.39 +         </plugin>
  268.40 +         <plugin>
  268.41               <groupId>org.codehaus.mojo</groupId>
  268.42               <artifactId>exec-maven-plugin</artifactId>
  268.43               <version>1.2.1</version>
  268.44 @@ -76,18 +83,24 @@
  268.45                   <execution>
  268.46                       <id>generate-js</id>
  268.47                       <phase>process-classes</phase>
  268.48 +                     <configuration>
  268.49 +                         <executable>java</executable>
  268.50 +                        <arguments>
  268.51 +                            <argument>-Dskip.if.exists=true</argument>
  268.52 +                            <argument>-cp</argument>
  268.53 +                            <classpath />
  268.54 +                            <argument>org.apidesign.vm4brwsr.Main</argument>
  268.55 +                            <argument>--obfuscatelevel</argument>
  268.56 +                            <argument>MINIMAL</argument>
  268.57 +                            <argument>${project.build.directory}/bck2brwsr.js</argument>
  268.58 +                            <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
  268.59 +                        </arguments>
  268.60 +                     </configuration>
  268.61                       <goals>
  268.62 -                         <goal>java</goal>
  268.63 +                         <goal>exec</goal>
  268.64                       </goals>
  268.65                   </execution>
  268.66               </executions>
  268.67 -             <configuration>
  268.68 -                 <mainClass>org.apidesign.vm4brwsr.Main</mainClass>
  268.69 -                 <arguments>
  268.70 -                     <argument>${project.build.directory}/bck2brwsr.js</argument>
  268.71 -                     <argument>org/apidesign/vm4brwsr/Bck2Brwsr</argument>
  268.72 -                 </arguments>
  268.73 -             </configuration>
  268.74           </plugin>
  268.75           <plugin>
  268.76               <artifactId>maven-assembly-plugin</artifactId>
  268.77 @@ -134,10 +147,16 @@
  268.78        <scope>compile</scope>
  268.79      </dependency>
  268.80      <dependency>
  268.81 -      <groupId>${project.groupId}</groupId>
  268.82 -      <artifactId>javap</artifactId>
  268.83 -      <version>${project.version}</version>
  268.84 +      <groupId>com.google.javascript</groupId>
  268.85 +      <artifactId>closure-compiler</artifactId>
  268.86 +      <version>r2388</version>
  268.87        <scope>compile</scope>
  268.88      </dependency>
  268.89 +    <dependency>
  268.90 +      <groupId>org.apidesign.html</groupId>
  268.91 +      <artifactId>net.java.html.boot</artifactId>
  268.92 +      <scope>test</scope>
  268.93 +      <version>${net.java.html.version}</version>
  268.94 +    </dependency>
  268.95    </dependencies>
  268.96  </project>
   269.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Wed Feb 27 17:50:47 2013 +0100
   269.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Bck2Brwsr.java	Mon Oct 07 14:20:58 2013 +0200
   269.3 @@ -54,46 +54,127 @@
   269.4   * @author Jaroslav Tulach <jtulach@netbeans.org>
   269.5   */
   269.6  public final class Bck2Brwsr {
   269.7 -    private Bck2Brwsr() {
   269.8 +    private final ObfuscationLevel level;
   269.9 +    private final StringArray classes;
  269.10 +    private final Resources res;
  269.11 +
  269.12 +    private Bck2Brwsr(ObfuscationLevel level, StringArray classes, Resources resources) {
  269.13 +        this.level = level;
  269.14 +        this.classes = classes;
  269.15 +        this.res = resources;
  269.16      }
  269.17      
  269.18 -    /** Generates virtual machine from bytes served by a <code>resources</code>
  269.19 +    /** Helper method to generate virtual machine from bytes served by a <code>resources</code>
  269.20       * provider.
  269.21 -     * 
  269.22 +     *
  269.23       * @param out the output to write the generated JavaScript to
  269.24       * @param resources provider of class files to use
  269.25       * @param classes additional classes to include in the generated script
  269.26       * @throws IOException I/O exception can be thrown when something goes wrong
  269.27       */
  269.28      public static void generate(Appendable out, Resources resources, String... classes) throws IOException {
  269.29 -        StringArray arr = StringArray.asList(classes);
  269.30 -        arr.add(VM.class.getName().replace('.', '/'));
  269.31 -        VM.compile(resources, out, arr);
  269.32 +        newCompiler().resources(resources).addRootClasses(classes).generate(out);
  269.33      }
  269.34 -    
  269.35 -    /** Generates virtual machine from bytes served by a class loader.
  269.36 -     * 
  269.37 +
  269.38 +    /** Helper method to generate virtual machine from bytes served by a class loader.
  269.39 +     *
  269.40       * @param out the output to write the generated JavaScript to
  269.41       * @param loader class loader to load needed classes from
  269.42       * @param classes additional classes to include in the generated script
  269.43       * @throws IOException I/O exception can be thrown when something goes wrong
  269.44       */
  269.45 -    public static void generate(Appendable out, final ClassLoader loader, String... classes) throws IOException {
  269.46 -        class R implements Resources {
  269.47 -            @Override
  269.48 -            public InputStream get(String name) throws IOException {
  269.49 -                Enumeration<URL> en = loader.getResources(name);
  269.50 -                URL u = null;
  269.51 -                while (en.hasMoreElements()) {
  269.52 -                    u = en.nextElement();
  269.53 -                }
  269.54 -                if (u == null) {
  269.55 -                    throw new IOException("Can't find " + name);
  269.56 -                }
  269.57 -                return u.openStream();
  269.58 +    public static void generate(Appendable out, ClassLoader loader, String... classes) throws IOException {
  269.59 +        newCompiler().resources(loader).addRootClasses(classes).generate(out);
  269.60 +    }
  269.61 +    
  269.62 +    /** Creates new instance of Bck2Brwsr compiler which is ready to generate
  269.63 +     * empty Bck2Brwsr virtual machine. The instance can be further
  269.64 +     * configured by calling chain of methods. For example: 
  269.65 +     * <pre>
  269.66 +     * {@link #createCompiler()}.{@link #resources(org.apidesign.vm4brwsr.Bck2Brwsr.Resources) resources(loader)}.{@link #addRootClasses(java.lang.String[]) addRootClasses("your/Clazz")}.{@link #generate(java.lang.Appendable) generate(out)};
  269.67 +     * </pre>
  269.68 +     * 
  269.69 +     * @return new instance of the Bck2Brwsr compiler
  269.70 +     * @since 0.5
  269.71 +     */
  269.72 +    public static Bck2Brwsr newCompiler() {
  269.73 +        StringArray arr = StringArray.asList(VM.class.getName().replace('.', '/'));
  269.74 +        return new Bck2Brwsr(ObfuscationLevel.NONE, arr, null);
  269.75 +    }
  269.76 +
  269.77 +    /** Creates new instance of the Bck2Brwsr compiler which inherits
  269.78 +     * all values from <code>this</code> instance and adds additional classes 
  269.79 +     * to the list of those that should be compiled by the {@link #generate(java.lang.Appendable)} 
  269.80 +     * method.
  269.81 +     * 
  269.82 +     * @param classes the classes to add to the compilation
  269.83 +     * @return new instance of the compiler
  269.84 +     */
  269.85 +    public Bck2Brwsr addRootClasses(String... classes) {
  269.86 +        if (classes.length == 0) {
  269.87 +            return this;
  269.88 +        } else {
  269.89 +            return new Bck2Brwsr(level, this.classes.addAndNew(classes), res);
  269.90 +        }
  269.91 +    }
  269.92 +    
  269.93 +    /** Changes the obfuscation level for the compiler by creating new instance
  269.94 +     * which inherits all values from <code>this</code> and adjust the level
  269.95 +     * of obfuscation.
  269.96 +     * 
  269.97 +     * @param level the new level of obfuscation
  269.98 +     * @return new instance of the compiler with changed level of obfuscation
  269.99 +     * @since 0.5
 269.100 +     */
 269.101 +    public Bck2Brwsr obfuscation(ObfuscationLevel level) {
 269.102 +        return new Bck2Brwsr(level, classes, res);
 269.103 +    }
 269.104 +    
 269.105 +    /** A way to change the provider of additional resources (classes) for the 
 269.106 +     * compiler. 
 269.107 +     * 
 269.108 +     * @param res the implementation of resources provider
 269.109 +     * @return new instance of the compiler with all values remaining the same, just 
 269.110 +     *   with different resources provider
 269.111 +     * @since 0.5
 269.112 +     */
 269.113 +    public Bck2Brwsr resources(Resources res) {
 269.114 +        return new Bck2Brwsr(level, classes, res);
 269.115 +    }
 269.116 +
 269.117 +    /** A way to change the provider of additional resources (classes) for the 
 269.118 +     * compiler by specifying classloader to use for loading them.
 269.119 +     * 
 269.120 +     * @param loader class loader to load the resources from
 269.121 +     * @return new instance of the compiler with all values being the same, just 
 269.122 +     *   different resources provider
 269.123 +     * @since 0.5
 269.124 +     */
 269.125 +    public Bck2Brwsr resources(final ClassLoader loader) {
 269.126 +        return resources(new LdrRsrcs(loader));
 269.127 +    }
 269.128 +    
 269.129 +    /** Generates virtual machine based on previous configuration of the 
 269.130 +     * compiler.
 269.131 +     * 
 269.132 +     * @param out the output to write the generated JavaScript to
 269.133 +     * @since 0.5
 269.134 +     */
 269.135 +    public void generate(Appendable out) throws IOException {
 269.136 +        Resources r = res != null ? res : new LdrRsrcs(Bck2Brwsr.class.getClassLoader());
 269.137 +        if (level != ObfuscationLevel.NONE) {
 269.138 +            try {
 269.139 +                ClosureWrapper.produceTo(out, level, r, classes);
 269.140 +                return;
 269.141 +            } catch (IOException ex) {
 269.142 +                throw ex;
 269.143 +            } catch (Throwable ex) {
 269.144 +                out.append("/* Failed to obfuscate: " + ex.getMessage()
 269.145 +                               + " */\n");
 269.146              }
 269.147          }
 269.148 -        generate(out, new R(), classes);
 269.149 +
 269.150 +        VM.compile(r, out, classes);
 269.151      }
 269.152      
 269.153      /** Provider of resources (classes and other files). The 
   270.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   270.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeParser.java	Mon Oct 07 14:20:58 2013 +0200
   270.3 @@ -0,0 +1,3461 @@
   270.4 +/*
   270.5 + * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
   270.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   270.7 + *
   270.8 + * This code is free software; you can redistribute it and/or modify it
   270.9 + * under the terms of the GNU General Public License version 2 only, as
  270.10 + * published by the Free Software Foundation.  Oracle designates this
  270.11 + * particular file as subject to the "Classpath" exception as provided
  270.12 + * by Oracle in the LICENSE file that accompanied this code.
  270.13 + *
  270.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
  270.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  270.16 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  270.17 + * version 2 for more details (a copy is included in the LICENSE file that
  270.18 + * accompanied this code).
  270.19 + *
  270.20 + * You should have received a copy of the GNU General Public License version
  270.21 + * 2 along with this work; if not, write to the Free Software Foundation,
  270.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  270.23 + *
  270.24 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  270.25 + * or visit www.oracle.com if you need additional information or have any
  270.26 + * questions.
  270.27 + */
  270.28 +package org.apidesign.vm4brwsr;
  270.29 +
  270.30 +import java.io.ByteArrayInputStream;
  270.31 +import java.io.DataInputStream;
  270.32 +import java.io.IOException;
  270.33 +import java.io.InputStream;
  270.34 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
  270.35 +import org.apidesign.bck2brwsr.core.JavaScriptPrototype;
  270.36 +
  270.37 +/** This is a byte code parser heavily based on original code of JavaP utility.
  270.38 + * As such I decided to keep the original Oracle's GPLv2 header.
  270.39 + *
  270.40 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  270.41 + */
  270.42 +final class ByteCodeParser {
  270.43 +    private ByteCodeParser() {
  270.44 +    }
  270.45 +    /* Signature Characters */
  270.46 +    public static final char   SIGC_VOID                  = 'V';
  270.47 +    public static final String SIG_VOID                   = "V";
  270.48 +    public static final char   SIGC_BOOLEAN               = 'Z';
  270.49 +    public static final String SIG_BOOLEAN                = "Z";
  270.50 +    public static final char   SIGC_BYTE                  = 'B';
  270.51 +    public static final String SIG_BYTE                   = "B";
  270.52 +    public static final char   SIGC_CHAR                  = 'C';
  270.53 +    public static final String SIG_CHAR                   = "C";
  270.54 +    public static final char   SIGC_SHORT                 = 'S';
  270.55 +    public static final String SIG_SHORT                  = "S";
  270.56 +    public static final char   SIGC_INT                   = 'I';
  270.57 +    public static final String SIG_INT                    = "I";
  270.58 +    public static final char   SIGC_LONG                  = 'J';
  270.59 +    public static final String SIG_LONG                   = "J";
  270.60 +    public static final char   SIGC_FLOAT                 = 'F';
  270.61 +    public static final String SIG_FLOAT                  = "F";
  270.62 +    public static final char   SIGC_DOUBLE                = 'D';
  270.63 +    public static final String SIG_DOUBLE                 = "D";
  270.64 +    public static final char   SIGC_ARRAY                 = '[';
  270.65 +    public static final String SIG_ARRAY                  = "[";
  270.66 +    public static final char   SIGC_CLASS                 = 'L';
  270.67 +    public static final String SIG_CLASS                  = "L";
  270.68 +    public static final char   SIGC_METHOD                = '(';
  270.69 +    public static final String SIG_METHOD                 = "(";
  270.70 +    public static final char   SIGC_ENDCLASS              = ';';
  270.71 +    public static final String SIG_ENDCLASS               = ";";
  270.72 +    public static final char   SIGC_ENDMETHOD             = ')';
  270.73 +    public static final String SIG_ENDMETHOD              = ")";
  270.74 +    public static final char   SIGC_PACKAGE               = '/';
  270.75 +    public static final String SIG_PACKAGE                = "/";
  270.76 +
  270.77 +    /* Class File Constants */
  270.78 +    public static final int JAVA_MAGIC                   = 0xcafebabe;
  270.79 +    public static final int JAVA_VERSION                 = 45;
  270.80 +    public static final int JAVA_MINOR_VERSION           = 3;
  270.81 +
  270.82 +    /* Constant table */
  270.83 +    public static final int CONSTANT_UTF8                = 1;
  270.84 +    public static final int CONSTANT_UNICODE             = 2;
  270.85 +    public static final int CONSTANT_INTEGER             = 3;
  270.86 +    public static final int CONSTANT_FLOAT               = 4;
  270.87 +    public static final int CONSTANT_LONG                = 5;
  270.88 +    public static final int CONSTANT_DOUBLE              = 6;
  270.89 +    public static final int CONSTANT_CLASS               = 7;
  270.90 +    public static final int CONSTANT_STRING              = 8;
  270.91 +    public static final int CONSTANT_FIELD               = 9;
  270.92 +    public static final int CONSTANT_METHOD              = 10;
  270.93 +    public static final int CONSTANT_INTERFACEMETHOD     = 11;
  270.94 +    public static final int CONSTANT_NAMEANDTYPE         = 12;
  270.95 +
  270.96 +    /* Access Flags */
  270.97 +    public static final int ACC_PUBLIC                   = 0x00000001;
  270.98 +    public static final int ACC_PRIVATE                  = 0x00000002;
  270.99 +    public static final int ACC_PROTECTED                = 0x00000004;
 270.100 +    public static final int ACC_STATIC                   = 0x00000008;
 270.101 +    public static final int ACC_FINAL                    = 0x00000010;
 270.102 +    public static final int ACC_SYNCHRONIZED             = 0x00000020;
 270.103 +    public static final int ACC_SUPER                        = 0x00000020;
 270.104 +    public static final int ACC_VOLATILE                 = 0x00000040;
 270.105 +    public static final int ACC_TRANSIENT                = 0x00000080;
 270.106 +    public static final int ACC_NATIVE                   = 0x00000100;
 270.107 +    public static final int ACC_INTERFACE                = 0x00000200;
 270.108 +    public static final int ACC_ABSTRACT                 = 0x00000400;
 270.109 +    public static final int ACC_STRICT                   = 0x00000800;
 270.110 +    public static final int ACC_EXPLICIT                 = 0x00001000;
 270.111 +    public static final int ACC_SYNTHETIC                = 0x00010000; // actually, this is an attribute
 270.112 +
 270.113 +    /* Type codes */
 270.114 +    public static final int T_CLASS                      = 0x00000002;
 270.115 +    public static final int T_BOOLEAN                    = 0x00000004;
 270.116 +    public static final int T_CHAR                       = 0x00000005;
 270.117 +    public static final int T_FLOAT                      = 0x00000006;
 270.118 +    public static final int T_DOUBLE                     = 0x00000007;
 270.119 +    public static final int T_BYTE                       = 0x00000008;
 270.120 +    public static final int T_SHORT                      = 0x00000009;
 270.121 +    public static final int T_INT                        = 0x0000000a;
 270.122 +    public static final int T_LONG                       = 0x0000000b;
 270.123 +
 270.124 +    /* Type codes for StackMap attribute */
 270.125 +    public static final int ITEM_Bogus      =0; // an unknown or uninitialized value
 270.126 +    public static final int ITEM_Integer    =1; // a 32-bit integer
 270.127 +    public static final int ITEM_Float      =2; // not used
 270.128 +    public static final int ITEM_Double     =3; // not used
 270.129 +    public static final int ITEM_Long       =4; // a 64-bit integer
 270.130 +    public static final int ITEM_Null       =5; // the type of null
 270.131 +    public static final int ITEM_InitObject =6; // "this" in constructor
 270.132 +    public static final int ITEM_Object     =7; // followed by 2-byte index of class name
 270.133 +    public static final int ITEM_NewObject  =8; // followed by 2-byte ref to "new"
 270.134 +
 270.135 +    /* Constants used in StackMapTable attribute */
 270.136 +    public static final int SAME_FRAME_BOUND                  = 64;
 270.137 +    public static final int SAME_LOCALS_1_STACK_ITEM_BOUND    = 128;
 270.138 +    public static final int SAME_LOCALS_1_STACK_ITEM_EXTENDED = 247;
 270.139 +    public static final int SAME_FRAME_EXTENDED               = 251;
 270.140 +    public static final int FULL_FRAME                        = 255;
 270.141 +
 270.142 +    /* Opcodes */
 270.143 +    public static final int opc_dead                     = -2;
 270.144 +    public static final int opc_label                    = -1;
 270.145 +    public static final int opc_nop                      = 0;
 270.146 +    public static final int opc_aconst_null              = 1;
 270.147 +    public static final int opc_iconst_m1                = 2;
 270.148 +    public static final int opc_iconst_0                 = 3;
 270.149 +    public static final int opc_iconst_1                 = 4;
 270.150 +    public static final int opc_iconst_2                 = 5;
 270.151 +    public static final int opc_iconst_3                 = 6;
 270.152 +    public static final int opc_iconst_4                 = 7;
 270.153 +    public static final int opc_iconst_5                 = 8;
 270.154 +    public static final int opc_lconst_0                 = 9;
 270.155 +    public static final int opc_lconst_1                 = 10;
 270.156 +    public static final int opc_fconst_0                 = 11;
 270.157 +    public static final int opc_fconst_1                 = 12;
 270.158 +    public static final int opc_fconst_2                 = 13;
 270.159 +    public static final int opc_dconst_0                 = 14;
 270.160 +    public static final int opc_dconst_1                 = 15;
 270.161 +    public static final int opc_bipush                   = 16;
 270.162 +    public static final int opc_sipush                   = 17;
 270.163 +    public static final int opc_ldc                      = 18;
 270.164 +    public static final int opc_ldc_w                    = 19;
 270.165 +    public static final int opc_ldc2_w                   = 20;
 270.166 +    public static final int opc_iload                    = 21;
 270.167 +    public static final int opc_lload                    = 22;
 270.168 +    public static final int opc_fload                    = 23;
 270.169 +    public static final int opc_dload                    = 24;
 270.170 +    public static final int opc_aload                    = 25;
 270.171 +    public static final int opc_iload_0                  = 26;
 270.172 +    public static final int opc_iload_1                  = 27;
 270.173 +    public static final int opc_iload_2                  = 28;
 270.174 +    public static final int opc_iload_3                  = 29;
 270.175 +    public static final int opc_lload_0                  = 30;
 270.176 +    public static final int opc_lload_1                  = 31;
 270.177 +    public static final int opc_lload_2                  = 32;
 270.178 +    public static final int opc_lload_3                  = 33;
 270.179 +    public static final int opc_fload_0                  = 34;
 270.180 +    public static final int opc_fload_1                  = 35;
 270.181 +    public static final int opc_fload_2                  = 36;
 270.182 +    public static final int opc_fload_3                  = 37;
 270.183 +    public static final int opc_dload_0                  = 38;
 270.184 +    public static final int opc_dload_1                  = 39;
 270.185 +    public static final int opc_dload_2                  = 40;
 270.186 +    public static final int opc_dload_3                  = 41;
 270.187 +    public static final int opc_aload_0                  = 42;
 270.188 +    public static final int opc_aload_1                  = 43;
 270.189 +    public static final int opc_aload_2                  = 44;
 270.190 +    public static final int opc_aload_3                  = 45;
 270.191 +    public static final int opc_iaload                   = 46;
 270.192 +    public static final int opc_laload                   = 47;
 270.193 +    public static final int opc_faload                   = 48;
 270.194 +    public static final int opc_daload                   = 49;
 270.195 +    public static final int opc_aaload                   = 50;
 270.196 +    public static final int opc_baload                   = 51;
 270.197 +    public static final int opc_caload                   = 52;
 270.198 +    public static final int opc_saload                   = 53;
 270.199 +    public static final int opc_istore                   = 54;
 270.200 +    public static final int opc_lstore                   = 55;
 270.201 +    public static final int opc_fstore                   = 56;
 270.202 +    public static final int opc_dstore                   = 57;
 270.203 +    public static final int opc_astore                   = 58;
 270.204 +    public static final int opc_istore_0                 = 59;
 270.205 +    public static final int opc_istore_1                 = 60;
 270.206 +    public static final int opc_istore_2                 = 61;
 270.207 +    public static final int opc_istore_3                 = 62;
 270.208 +    public static final int opc_lstore_0                 = 63;
 270.209 +    public static final int opc_lstore_1                 = 64;
 270.210 +    public static final int opc_lstore_2                 = 65;
 270.211 +    public static final int opc_lstore_3                 = 66;
 270.212 +    public static final int opc_fstore_0                 = 67;
 270.213 +    public static final int opc_fstore_1                 = 68;
 270.214 +    public static final int opc_fstore_2                 = 69;
 270.215 +    public static final int opc_fstore_3                 = 70;
 270.216 +    public static final int opc_dstore_0                 = 71;
 270.217 +    public static final int opc_dstore_1                 = 72;
 270.218 +    public static final int opc_dstore_2                 = 73;
 270.219 +    public static final int opc_dstore_3                 = 74;
 270.220 +    public static final int opc_astore_0                 = 75;
 270.221 +    public static final int opc_astore_1                 = 76;
 270.222 +    public static final int opc_astore_2                 = 77;
 270.223 +    public static final int opc_astore_3                 = 78;
 270.224 +    public static final int opc_iastore                  = 79;
 270.225 +    public static final int opc_lastore                  = 80;
 270.226 +    public static final int opc_fastore                  = 81;
 270.227 +    public static final int opc_dastore                  = 82;
 270.228 +    public static final int opc_aastore                  = 83;
 270.229 +    public static final int opc_bastore                  = 84;
 270.230 +    public static final int opc_castore                  = 85;
 270.231 +    public static final int opc_sastore                  = 86;
 270.232 +    public static final int opc_pop                      = 87;
 270.233 +    public static final int opc_pop2                     = 88;
 270.234 +    public static final int opc_dup                      = 89;
 270.235 +    public static final int opc_dup_x1                   = 90;
 270.236 +    public static final int opc_dup_x2                   = 91;
 270.237 +    public static final int opc_dup2                     = 92;
 270.238 +    public static final int opc_dup2_x1                  = 93;
 270.239 +    public static final int opc_dup2_x2                  = 94;
 270.240 +    public static final int opc_swap                     = 95;
 270.241 +    public static final int opc_iadd                     = 96;
 270.242 +    public static final int opc_ladd                     = 97;
 270.243 +    public static final int opc_fadd                     = 98;
 270.244 +    public static final int opc_dadd                     = 99;
 270.245 +    public static final int opc_isub                     = 100;
 270.246 +    public static final int opc_lsub                     = 101;
 270.247 +    public static final int opc_fsub                     = 102;
 270.248 +    public static final int opc_dsub                     = 103;
 270.249 +    public static final int opc_imul                     = 104;
 270.250 +    public static final int opc_lmul                     = 105;
 270.251 +    public static final int opc_fmul                     = 106;
 270.252 +    public static final int opc_dmul                     = 107;
 270.253 +    public static final int opc_idiv                     = 108;
 270.254 +    public static final int opc_ldiv                     = 109;
 270.255 +    public static final int opc_fdiv                     = 110;
 270.256 +    public static final int opc_ddiv                     = 111;
 270.257 +    public static final int opc_irem                     = 112;
 270.258 +    public static final int opc_lrem                     = 113;
 270.259 +    public static final int opc_frem                     = 114;
 270.260 +    public static final int opc_drem                     = 115;
 270.261 +    public static final int opc_ineg                     = 116;
 270.262 +    public static final int opc_lneg                     = 117;
 270.263 +    public static final int opc_fneg                     = 118;
 270.264 +    public static final int opc_dneg                     = 119;
 270.265 +    public static final int opc_ishl                     = 120;
 270.266 +    public static final int opc_lshl                     = 121;
 270.267 +    public static final int opc_ishr                     = 122;
 270.268 +    public static final int opc_lshr                     = 123;
 270.269 +    public static final int opc_iushr                    = 124;
 270.270 +    public static final int opc_lushr                    = 125;
 270.271 +    public static final int opc_iand                     = 126;
 270.272 +    public static final int opc_land                     = 127;
 270.273 +    public static final int opc_ior                      = 128;
 270.274 +    public static final int opc_lor                      = 129;
 270.275 +    public static final int opc_ixor                     = 130;
 270.276 +    public static final int opc_lxor                     = 131;
 270.277 +    public static final int opc_iinc                     = 132;
 270.278 +    public static final int opc_i2l                      = 133;
 270.279 +    public static final int opc_i2f                      = 134;
 270.280 +    public static final int opc_i2d                      = 135;
 270.281 +    public static final int opc_l2i                      = 136;
 270.282 +    public static final int opc_l2f                      = 137;
 270.283 +    public static final int opc_l2d                      = 138;
 270.284 +    public static final int opc_f2i                      = 139;
 270.285 +    public static final int opc_f2l                      = 140;
 270.286 +    public static final int opc_f2d                      = 141;
 270.287 +    public static final int opc_d2i                      = 142;
 270.288 +    public static final int opc_d2l                      = 143;
 270.289 +    public static final int opc_d2f                      = 144;
 270.290 +    public static final int opc_i2b                      = 145;
 270.291 +    public static final int opc_int2byte                 = 145;
 270.292 +    public static final int opc_i2c                      = 146;
 270.293 +    public static final int opc_int2char                 = 146;
 270.294 +    public static final int opc_i2s                      = 147;
 270.295 +    public static final int opc_int2short                = 147;
 270.296 +    public static final int opc_lcmp                     = 148;
 270.297 +    public static final int opc_fcmpl                    = 149;
 270.298 +    public static final int opc_fcmpg                    = 150;
 270.299 +    public static final int opc_dcmpl                    = 151;
 270.300 +    public static final int opc_dcmpg                    = 152;
 270.301 +    public static final int opc_ifeq                     = 153;
 270.302 +    public static final int opc_ifne                     = 154;
 270.303 +    public static final int opc_iflt                     = 155;
 270.304 +    public static final int opc_ifge                     = 156;
 270.305 +    public static final int opc_ifgt                     = 157;
 270.306 +    public static final int opc_ifle                     = 158;
 270.307 +    public static final int opc_if_icmpeq                = 159;
 270.308 +    public static final int opc_if_icmpne                = 160;
 270.309 +    public static final int opc_if_icmplt                = 161;
 270.310 +    public static final int opc_if_icmpge                = 162;
 270.311 +    public static final int opc_if_icmpgt                = 163;
 270.312 +    public static final int opc_if_icmple                = 164;
 270.313 +    public static final int opc_if_acmpeq                = 165;
 270.314 +    public static final int opc_if_acmpne                = 166;
 270.315 +    public static final int opc_goto                     = 167;
 270.316 +    public static final int opc_jsr                      = 168;
 270.317 +    public static final int opc_ret                      = 169;
 270.318 +    public static final int opc_tableswitch              = 170;
 270.319 +    public static final int opc_lookupswitch             = 171;
 270.320 +    public static final int opc_ireturn                  = 172;
 270.321 +    public static final int opc_lreturn                  = 173;
 270.322 +    public static final int opc_freturn                  = 174;
 270.323 +    public static final int opc_dreturn                  = 175;
 270.324 +    public static final int opc_areturn                  = 176;
 270.325 +    public static final int opc_return                   = 177;
 270.326 +    public static final int opc_getstatic                = 178;
 270.327 +    public static final int opc_putstatic                = 179;
 270.328 +    public static final int opc_getfield                 = 180;
 270.329 +    public static final int opc_putfield                 = 181;
 270.330 +    public static final int opc_invokevirtual            = 182;
 270.331 +    public static final int opc_invokenonvirtual         = 183;
 270.332 +    public static final int opc_invokespecial            = 183;
 270.333 +    public static final int opc_invokestatic             = 184;
 270.334 +    public static final int opc_invokeinterface          = 185;
 270.335 +//    public static final int opc_xxxunusedxxx             = 186;
 270.336 +    public static final int opc_new                      = 187;
 270.337 +    public static final int opc_newarray                 = 188;
 270.338 +    public static final int opc_anewarray                = 189;
 270.339 +    public static final int opc_arraylength              = 190;
 270.340 +    public static final int opc_athrow                   = 191;
 270.341 +    public static final int opc_checkcast                = 192;
 270.342 +    public static final int opc_instanceof               = 193;
 270.343 +    public static final int opc_monitorenter             = 194;
 270.344 +    public static final int opc_monitorexit              = 195;
 270.345 +    public static final int opc_wide                     = 196;
 270.346 +    public static final int opc_multianewarray           = 197;
 270.347 +    public static final int opc_ifnull                   = 198;
 270.348 +    public static final int opc_ifnonnull                = 199;
 270.349 +    public static final int opc_goto_w                   = 200;
 270.350 +    public static final int opc_jsr_w                    = 201;
 270.351 +        /* Pseudo-instructions */
 270.352 +    public static final int opc_bytecode                 = 203;
 270.353 +    public static final int opc_try                      = 204;
 270.354 +    public static final int opc_endtry                   = 205;
 270.355 +    public static final int opc_catch                    = 206;
 270.356 +    public static final int opc_var                      = 207;
 270.357 +    public static final int opc_endvar                   = 208;
 270.358 +    public static final int opc_localsmap                = 209;
 270.359 +    public static final int opc_stackmap                 = 210;
 270.360 +        /* PicoJava prefixes */
 270.361 +    public static final int opc_nonpriv                  = 254;
 270.362 +    public static final int opc_priv                     = 255;
 270.363 +
 270.364 +        /* Wide instructions */
 270.365 +    public static final int opc_iload_w         = (opc_wide<<8)|opc_iload;
 270.366 +    public static final int opc_lload_w         = (opc_wide<<8)|opc_lload;
 270.367 +    public static final int opc_fload_w         = (opc_wide<<8)|opc_fload;
 270.368 +    public static final int opc_dload_w         = (opc_wide<<8)|opc_dload;
 270.369 +    public static final int opc_aload_w         = (opc_wide<<8)|opc_aload;
 270.370 +    public static final int opc_istore_w        = (opc_wide<<8)|opc_istore;
 270.371 +    public static final int opc_lstore_w        = (opc_wide<<8)|opc_lstore;
 270.372 +    public static final int opc_fstore_w        = (opc_wide<<8)|opc_fstore;
 270.373 +    public static final int opc_dstore_w        = (opc_wide<<8)|opc_dstore;
 270.374 +    public static final int opc_astore_w        = (opc_wide<<8)|opc_astore;
 270.375 +    public static final int opc_ret_w           = (opc_wide<<8)|opc_ret;
 270.376 +    public static final int opc_iinc_w          = (opc_wide<<8)|opc_iinc;
 270.377 +
 270.378 +    /* Opcode Names */
 270.379 +  public static final String opcNamesTab[] = {
 270.380 +        "nop",
 270.381 +        "aconst_null",
 270.382 +        "iconst_m1",
 270.383 +        "iconst_0",
 270.384 +        "iconst_1",
 270.385 +        "iconst_2",
 270.386 +        "iconst_3",
 270.387 +        "iconst_4",
 270.388 +        "iconst_5",
 270.389 +        "lconst_0",
 270.390 +        "lconst_1",
 270.391 +        "fconst_0",
 270.392 +        "fconst_1",
 270.393 +        "fconst_2",
 270.394 +        "dconst_0",
 270.395 +        "dconst_1",
 270.396 +        "bipush",
 270.397 +        "sipush",
 270.398 +        "ldc",
 270.399 +        "ldc_w",
 270.400 +        "ldc2_w",
 270.401 +        "iload",
 270.402 +        "lload",
 270.403 +        "fload",
 270.404 +        "dload",
 270.405 +        "aload",
 270.406 +        "iload_0",
 270.407 +        "iload_1",
 270.408 +        "iload_2",
 270.409 +        "iload_3",
 270.410 +        "lload_0",
 270.411 +        "lload_1",
 270.412 +        "lload_2",
 270.413 +        "lload_3",
 270.414 +        "fload_0",
 270.415 +        "fload_1",
 270.416 +        "fload_2",
 270.417 +        "fload_3",
 270.418 +        "dload_0",
 270.419 +        "dload_1",
 270.420 +        "dload_2",
 270.421 +        "dload_3",
 270.422 +        "aload_0",
 270.423 +        "aload_1",
 270.424 +        "aload_2",
 270.425 +        "aload_3",
 270.426 +        "iaload",
 270.427 +        "laload",
 270.428 +        "faload",
 270.429 +        "daload",
 270.430 +        "aaload",
 270.431 +        "baload",
 270.432 +        "caload",
 270.433 +        "saload",
 270.434 +        "istore",
 270.435 +        "lstore",
 270.436 +        "fstore",
 270.437 +        "dstore",
 270.438 +        "astore",
 270.439 +        "istore_0",
 270.440 +        "istore_1",
 270.441 +        "istore_2",
 270.442 +        "istore_3",
 270.443 +        "lstore_0",
 270.444 +        "lstore_1",
 270.445 +        "lstore_2",
 270.446 +        "lstore_3",
 270.447 +        "fstore_0",
 270.448 +        "fstore_1",
 270.449 +        "fstore_2",
 270.450 +        "fstore_3",
 270.451 +        "dstore_0",
 270.452 +        "dstore_1",
 270.453 +        "dstore_2",
 270.454 +        "dstore_3",
 270.455 +        "astore_0",
 270.456 +        "astore_1",
 270.457 +        "astore_2",
 270.458 +        "astore_3",
 270.459 +        "iastore",
 270.460 +        "lastore",
 270.461 +        "fastore",
 270.462 +        "dastore",
 270.463 +        "aastore",
 270.464 +        "bastore",
 270.465 +        "castore",
 270.466 +        "sastore",
 270.467 +        "pop",
 270.468 +        "pop2",
 270.469 +        "dup",
 270.470 +        "dup_x1",
 270.471 +        "dup_x2",
 270.472 +        "dup2",
 270.473 +        "dup2_x1",
 270.474 +        "dup2_x2",
 270.475 +        "swap",
 270.476 +        "iadd",
 270.477 +        "ladd",
 270.478 +        "fadd",
 270.479 +        "dadd",
 270.480 +        "isub",
 270.481 +        "lsub",
 270.482 +        "fsub",
 270.483 +        "dsub",
 270.484 +        "imul",
 270.485 +        "lmul",
 270.486 +        "fmul",
 270.487 +        "dmul",
 270.488 +        "idiv",
 270.489 +        "ldiv",
 270.490 +        "fdiv",
 270.491 +        "ddiv",
 270.492 +        "irem",
 270.493 +        "lrem",
 270.494 +        "frem",
 270.495 +        "drem",
 270.496 +        "ineg",
 270.497 +        "lneg",
 270.498 +        "fneg",
 270.499 +        "dneg",
 270.500 +        "ishl",
 270.501 +        "lshl",
 270.502 +        "ishr",
 270.503 +        "lshr",
 270.504 +        "iushr",
 270.505 +        "lushr",
 270.506 +        "iand",
 270.507 +        "land",
 270.508 +        "ior",
 270.509 +        "lor",
 270.510 +        "ixor",
 270.511 +        "lxor",
 270.512 +        "iinc",
 270.513 +        "i2l",
 270.514 +        "i2f",
 270.515 +        "i2d",
 270.516 +        "l2i",
 270.517 +        "l2f",
 270.518 +        "l2d",
 270.519 +        "f2i",
 270.520 +        "f2l",
 270.521 +        "f2d",
 270.522 +        "d2i",
 270.523 +        "d2l",
 270.524 +        "d2f",
 270.525 +        "i2b",
 270.526 +        "i2c",
 270.527 +        "i2s",
 270.528 +        "lcmp",
 270.529 +        "fcmpl",
 270.530 +        "fcmpg",
 270.531 +        "dcmpl",
 270.532 +        "dcmpg",
 270.533 +        "ifeq",
 270.534 +        "ifne",
 270.535 +        "iflt",
 270.536 +        "ifge",
 270.537 +        "ifgt",
 270.538 +        "ifle",
 270.539 +        "if_icmpeq",
 270.540 +        "if_icmpne",
 270.541 +        "if_icmplt",
 270.542 +        "if_icmpge",
 270.543 +        "if_icmpgt",
 270.544 +        "if_icmple",
 270.545 +        "if_acmpeq",
 270.546 +        "if_acmpne",
 270.547 +        "goto",
 270.548 +        "jsr",
 270.549 +        "ret",
 270.550 +        "tableswitch",
 270.551 +        "lookupswitch",
 270.552 +        "ireturn",
 270.553 +        "lreturn",
 270.554 +        "freturn",
 270.555 +        "dreturn",
 270.556 +        "areturn",
 270.557 +        "return",
 270.558 +        "getstatic",
 270.559 +        "putstatic",
 270.560 +        "getfield",
 270.561 +        "putfield",
 270.562 +        "invokevirtual",
 270.563 +        "invokespecial", //     was "invokenonvirtual",
 270.564 +        "invokestatic",
 270.565 +        "invokeinterface",
 270.566 +        "bytecode 186", //"xxxunusedxxx",
 270.567 +        "new",
 270.568 +        "newarray",
 270.569 +        "anewarray",
 270.570 +        "arraylength",
 270.571 +        "athrow",
 270.572 +        "checkcast",
 270.573 +        "instanceof",
 270.574 +        "monitorenter",
 270.575 +        "monitorexit",
 270.576 +         null, // "wide",
 270.577 +        "multianewarray",
 270.578 +        "ifnull",
 270.579 +        "ifnonnull",
 270.580 +        "goto_w",
 270.581 +        "jsr_w",
 270.582 +        "bytecode 202", // "breakpoint",
 270.583 +        "bytecode",
 270.584 +        "try",
 270.585 +        "endtry",
 270.586 +        "catch",
 270.587 +        "var",
 270.588 +        "endvar",
 270.589 +        "locals_map",
 270.590 +        "stack_map"
 270.591 +  };
 270.592 +
 270.593 +    /* Opcode Lengths */
 270.594 +  public static final int opcLengthsTab[] = {
 270.595 +        1,
 270.596 +        1,
 270.597 +        1,
 270.598 +        1,
 270.599 +        1,
 270.600 +        1,
 270.601 +        1,
 270.602 +        1,
 270.603 +        1,
 270.604 +        1,
 270.605 +        1,
 270.606 +        1,
 270.607 +        1,
 270.608 +        1,
 270.609 +        1,
 270.610 +        1,
 270.611 +        2,
 270.612 +        3,
 270.613 +        2,
 270.614 +        3,
 270.615 +        3,
 270.616 +        2,
 270.617 +        2,
 270.618 +        2,
 270.619 +        2,
 270.620 +        2,
 270.621 +        1,
 270.622 +        1,
 270.623 +        1,
 270.624 +        1,
 270.625 +        1,
 270.626 +        1,
 270.627 +        1,
 270.628 +        1,
 270.629 +        1,
 270.630 +        1,
 270.631 +        1,
 270.632 +        1,
 270.633 +        1,
 270.634 +        1,
 270.635 +        1,
 270.636 +        1,
 270.637 +        1,
 270.638 +        1,
 270.639 +        1,
 270.640 +        1,
 270.641 +        1,
 270.642 +        1,
 270.643 +        1,
 270.644 +        1,
 270.645 +        1,
 270.646 +        1,
 270.647 +        1,
 270.648 +        1,
 270.649 +        2,
 270.650 +        2,
 270.651 +        2,
 270.652 +        2,
 270.653 +        2,
 270.654 +        1,
 270.655 +        1,
 270.656 +        1,
 270.657 +        1,
 270.658 +        1,
 270.659 +        1,
 270.660 +        1,
 270.661 +        1,
 270.662 +        1,
 270.663 +        1,
 270.664 +        1,
 270.665 +        1,
 270.666 +        1,
 270.667 +        1,
 270.668 +        1,
 270.669 +        1,
 270.670 +        1,
 270.671 +        1,
 270.672 +        1,
 270.673 +        1,
 270.674 +        1,
 270.675 +        1,
 270.676 +        1,
 270.677 +        1,
 270.678 +        1,
 270.679 +        1,
 270.680 +        1,
 270.681 +        1,
 270.682 +        1,
 270.683 +        1,
 270.684 +        1,
 270.685 +        1,
 270.686 +        1,
 270.687 +        1,
 270.688 +        1,
 270.689 +        1,
 270.690 +        1,
 270.691 +        1,
 270.692 +        1,
 270.693 +        1,
 270.694 +        1,
 270.695 +        1,
 270.696 +        1,
 270.697 +        1,
 270.698 +        1,
 270.699 +        1,
 270.700 +        1,
 270.701 +        1,
 270.702 +        1,
 270.703 +        1,
 270.704 +        1,
 270.705 +        1,
 270.706 +        1,
 270.707 +        1,
 270.708 +        1,
 270.709 +        1,
 270.710 +        1,
 270.711 +        1,
 270.712 +        1,
 270.713 +        1,
 270.714 +        1,
 270.715 +        1,
 270.716 +        1,
 270.717 +        1,
 270.718 +        1,
 270.719 +        1,
 270.720 +        1,
 270.721 +        1,
 270.722 +        1,
 270.723 +        1,
 270.724 +        1,
 270.725 +        1,
 270.726 +        1,
 270.727 +        3,
 270.728 +        1,
 270.729 +        1,
 270.730 +        1,
 270.731 +        1,
 270.732 +        1,
 270.733 +        1,
 270.734 +        1,
 270.735 +        1,
 270.736 +        1,
 270.737 +        1,
 270.738 +        1,
 270.739 +        1,
 270.740 +        1,
 270.741 +        1,
 270.742 +        1,
 270.743 +        1,
 270.744 +        1,
 270.745 +        1,
 270.746 +        1,
 270.747 +        1,
 270.748 +        3,
 270.749 +        3,
 270.750 +        3,
 270.751 +        3,
 270.752 +        3,
 270.753 +        3,
 270.754 +        3,
 270.755 +        3,
 270.756 +        3,
 270.757 +        3,
 270.758 +        3,
 270.759 +        3,
 270.760 +        3,
 270.761 +        3,
 270.762 +        3,
 270.763 +        3,
 270.764 +        2,
 270.765 +        99,
 270.766 +        99,
 270.767 +        1,
 270.768 +        1,
 270.769 +        1,
 270.770 +        1,
 270.771 +        1,
 270.772 +        1,
 270.773 +        3,
 270.774 +        3,
 270.775 +        3,
 270.776 +        3,
 270.777 +        3,
 270.778 +        3,
 270.779 +        3,
 270.780 +        5,
 270.781 +        0,
 270.782 +        3,
 270.783 +        2,
 270.784 +        3,
 270.785 +        1,
 270.786 +        1,
 270.787 +        3,
 270.788 +        3,
 270.789 +        1,
 270.790 +        1,
 270.791 +        0, // wide
 270.792 +        4,
 270.793 +        3,
 270.794 +        3,
 270.795 +        5,
 270.796 +        5,
 270.797 +        1,
 270.798 +        1, 0, 0, 0, 0, 0 // pseudo
 270.799 +  };
 270.800 +
 270.801 +     /**
 270.802 +     * End of input
 270.803 +     */
 270.804 +    public static final int EOF = -1;
 270.805 +
 270.806 +   /*
 270.807 +     * Flags
 270.808 +     */
 270.809 +    public static final int F_VERBOSE           = 1 << 0;
 270.810 +    public static final int F_DUMP              = 1 << 1;
 270.811 +    public static final int F_WARNINGS          = 1 << 2;
 270.812 +    public static final int F_DEBUG             = 1 << 3;
 270.813 +    public static final int F_OPTIMIZE          = 1 << 4;
 270.814 +    public static final int F_DEPENDENCIES      = 1 << 5;
 270.815 +
 270.816 +    /*
 270.817 +     * Type codes
 270.818 +     */
 270.819 +    public static final int TC_BOOLEAN   = 0;
 270.820 +    public static final int TC_BYTE      = 1;
 270.821 +    public static final int TC_CHAR      = 2;
 270.822 +    public static final int TC_SHORT     = 3;
 270.823 +    public static final int TC_INT       = 4;
 270.824 +    public static final int TC_LONG      = 5;
 270.825 +    public static final int TC_FLOAT     = 6;
 270.826 +    public static final int TC_DOUBLE    = 7;
 270.827 +    public static final int TC_NULL      = 8;
 270.828 +    public static final int TC_ARRAY     = 9;
 270.829 +    public static final int TC_CLASS     = 10;
 270.830 +    public static final int TC_VOID      = 11;
 270.831 +    public static final int TC_METHOD    = 12;
 270.832 +    public static final int TC_ERROR     = 13;
 270.833 +
 270.834 +    /*
 270.835 +     * Type Masks
 270.836 +     */
 270.837 +    public static final int TM_NULL      = 1 << TC_NULL;
 270.838 +    public static final int TM_VOID      = 1 << TC_VOID;
 270.839 +    public static final int TM_BOOLEAN   = 1 << TC_BOOLEAN;
 270.840 +    public static final int TM_BYTE      = 1 << TC_BYTE;
 270.841 +    public static final int TM_CHAR      = 1 << TC_CHAR;
 270.842 +    public static final int TM_SHORT     = 1 << TC_SHORT;
 270.843 +    public static final int TM_INT       = 1 << TC_INT;
 270.844 +    public static final int TM_LONG      = 1 << TC_LONG;
 270.845 +    public static final int TM_FLOAT     = 1 << TC_FLOAT;
 270.846 +    public static final int TM_DOUBLE    = 1 << TC_DOUBLE;
 270.847 +    public static final int TM_ARRAY     = 1 << TC_ARRAY;
 270.848 +    public static final int TM_CLASS     = 1 << TC_CLASS;
 270.849 +    public static final int TM_METHOD    = 1 << TC_METHOD;
 270.850 +    public static final int TM_ERROR     = 1 << TC_ERROR;
 270.851 +
 270.852 +    public static final int TM_INT32     = TM_BYTE | TM_SHORT | TM_CHAR | TM_INT;
 270.853 +    public static final int TM_NUM32     = TM_INT32 | TM_FLOAT;
 270.854 +    public static final int TM_NUM64     = TM_LONG | TM_DOUBLE;
 270.855 +    public static final int TM_INTEGER   = TM_INT32 | TM_LONG;
 270.856 +    public static final int TM_REAL      = TM_FLOAT | TM_DOUBLE;
 270.857 +    public static final int TM_NUMBER    = TM_INTEGER | TM_REAL;
 270.858 +    public static final int TM_REFERENCE = TM_ARRAY | TM_CLASS | TM_NULL;
 270.859 +
 270.860 +    /*
 270.861 +     * Class status
 270.862 +     */
 270.863 +    public static final int CS_UNDEFINED        = 0;
 270.864 +    public static final int CS_UNDECIDED        = 1;
 270.865 +    public static final int CS_BINARY           = 2;
 270.866 +    public static final int CS_SOURCE           = 3;
 270.867 +    public static final int CS_PARSED           = 4;
 270.868 +    public static final int CS_COMPILED         = 5;
 270.869 +    public static final int CS_NOTFOUND         = 6;
 270.870 +
 270.871 +    /*
 270.872 +     * Attributes
 270.873 +     */
 270.874 +    public static final int ATT_ALL             = -1;
 270.875 +    public static final int ATT_CODE            = 1;
 270.876 +
 270.877 +    /*
 270.878 +     * Number of bits used in file offsets
 270.879 +     */
 270.880 +    public static final int OFFSETBITS          = 19;
 270.881 +    public static final int MAXFILESIZE         = (1 << OFFSETBITS) - 1;
 270.882 +    public static final int MAXLINENUMBER       = (1 << (32 - OFFSETBITS)) - 1;
 270.883 +
 270.884 +    /*
 270.885 +     * Operators
 270.886 +     */
 270.887 +    public final int COMMA              = 0;
 270.888 +    public final int ASSIGN             = 1;
 270.889 +
 270.890 +    public final int ASGMUL             = 2;
 270.891 +    public final int ASGDIV             = 3;
 270.892 +    public final int ASGREM             = 4;
 270.893 +    public final int ASGADD             = 5;
 270.894 +    public final int ASGSUB             = 6;
 270.895 +    public final int ASGLSHIFT          = 7;
 270.896 +    public final int ASGRSHIFT          = 8;
 270.897 +    public final int ASGURSHIFT         = 9;
 270.898 +    public final int ASGBITAND          = 10;
 270.899 +    public final int ASGBITOR           = 11;
 270.900 +    public final int ASGBITXOR          = 12;
 270.901 +
 270.902 +    public final int COND               = 13;
 270.903 +    public final int OR                 = 14;
 270.904 +    public final int AND                = 15;
 270.905 +    public final int BITOR              = 16;
 270.906 +    public final int BITXOR             = 17;
 270.907 +    public final int BITAND             = 18;
 270.908 +    public final int NE                 = 19;
 270.909 +    public final int EQ                 = 20;
 270.910 +    public final int GE                 = 21;
 270.911 +    public final int GT                 = 22;
 270.912 +    public final int LE                 = 23;
 270.913 +    public final int LT                 = 24;
 270.914 +    public final int INSTANCEOF         = 25;
 270.915 +    public final int LSHIFT             = 26;
 270.916 +    public final int RSHIFT             = 27;
 270.917 +    public final int URSHIFT            = 28;
 270.918 +    public final int ADD                = 29;
 270.919 +    public final int SUB                = 30;
 270.920 +    public final int DIV                = 31;
 270.921 +    public final int REM                = 32;
 270.922 +    public final int MUL                = 33;
 270.923 +    public final int CAST               = 34;           // (x)y
 270.924 +    public final int POS                = 35;           // +x
 270.925 +    public final int NEG                = 36;           // -x
 270.926 +    public final int NOT                = 37;
 270.927 +    public final int BITNOT             = 38;
 270.928 +    public final int PREINC             = 39;           // ++x
 270.929 +    public final int PREDEC             = 40;           // --x
 270.930 +    public final int NEWARRAY           = 41;
 270.931 +    public final int NEWINSTANCE        = 42;
 270.932 +    public final int NEWFROMNAME        = 43;
 270.933 +    public final int POSTINC            = 44;           // x++
 270.934 +    public final int POSTDEC            = 45;           // x--
 270.935 +    public final int FIELD              = 46;
 270.936 +    public final int METHOD             = 47;           // x(y)
 270.937 +    public final int ARRAYACCESS        = 48;           // x[y]
 270.938 +    public final int NEW                = 49;
 270.939 +    public final int INC                = 50;
 270.940 +    public final int DEC                = 51;
 270.941 +
 270.942 +    public final int CONVERT            = 55;           // implicit conversion
 270.943 +    public final int EXPR               = 56;           // (x)
 270.944 +    public final int ARRAY              = 57;           // {x, y, ...}
 270.945 +    public final int GOTO               = 58;
 270.946 +
 270.947 +    /*
 270.948 +     * Value tokens
 270.949 +     */
 270.950 +    public final int IDENT              = 60;
 270.951 +    public final int BOOLEANVAL         = 61;
 270.952 +    public final int BYTEVAL            = 62;
 270.953 +    public final int CHARVAL            = 63;
 270.954 +    public final int SHORTVAL           = 64;
 270.955 +    public final int INTVAL                     = 65;
 270.956 +    public final int LONGVAL            = 66;
 270.957 +    public final int FLOATVAL           = 67;
 270.958 +    public final int DOUBLEVAL          = 68;
 270.959 +    public final int STRINGVAL          = 69;
 270.960 +
 270.961 +    /*
 270.962 +     * Type keywords
 270.963 +     */
 270.964 +    public final int BYTE               = 70;
 270.965 +    public final int CHAR               = 71;
 270.966 +    public final int SHORT              = 72;
 270.967 +    public final int INT                = 73;
 270.968 +    public final int LONG               = 74;
 270.969 +    public final int FLOAT              = 75;
 270.970 +    public final int DOUBLE             = 76;
 270.971 +    public final int VOID               = 77;
 270.972 +    public final int BOOLEAN            = 78;
 270.973 +
 270.974 +    /*
 270.975 +     * Expression keywords
 270.976 +     */
 270.977 +    public final int TRUE               = 80;
 270.978 +    public final int FALSE              = 81;
 270.979 +    public final int THIS               = 82;
 270.980 +    public final int SUPER              = 83;
 270.981 +    public final int NULL               = 84;
 270.982 +
 270.983 +    /*
 270.984 +     * Statement keywords
 270.985 +     */
 270.986 +    public final int IF                 = 90;
 270.987 +    public final int ELSE               = 91;
 270.988 +    public final int FOR                = 92;
 270.989 +    public final int WHILE              = 93;
 270.990 +    public final int DO                 = 94;
 270.991 +    public final int SWITCH             = 95;
 270.992 +    public final int CASE               = 96;
 270.993 +    public final int DEFAULT            = 97;
 270.994 +    public final int BREAK              = 98;
 270.995 +    public final int CONTINUE           = 99;
 270.996 +    public final int RETURN             = 100;
 270.997 +    public final int TRY                = 101;
 270.998 +    public final int CATCH              = 102;
 270.999 +    public final int FINALLY            = 103;
270.1000 +    public final int THROW              = 104;
270.1001 +    public final int STAT               = 105;
270.1002 +    public final int EXPRESSION         = 106;
270.1003 +    public final int DECLARATION        = 107;
270.1004 +    public final int VARDECLARATION     = 108;
270.1005 +
270.1006 +    /*
270.1007 +     * Declaration keywords
270.1008 +     */
270.1009 +    public final int IMPORT             = 110;
270.1010 +    public final int CLASS              = 111;
270.1011 +    public final int EXTENDS            = 112;
270.1012 +    public final int IMPLEMENTS         = 113;
270.1013 +    public final int INTERFACE          = 114;
270.1014 +    public final int PACKAGE            = 115;
270.1015 +
270.1016 +    /*
270.1017 +     * Modifier keywords
270.1018 +     */
270.1019 +    public final int PRIVATE    = 120;
270.1020 +    public final int PUBLIC             = 121;
270.1021 +    public final int PROTECTED  = 122;
270.1022 +    public final int CONST              = 123;
270.1023 +    public final int STATIC             = 124;
270.1024 +    public final int TRANSIENT          = 125;
270.1025 +    public final int SYNCHRONIZED       = 126;
270.1026 +    public final int NATIVE             = 127;
270.1027 +    public final int FINAL              = 128;
270.1028 +    public final int VOLATILE   = 129;
270.1029 +    public final int ABSTRACT   = 130;
270.1030 +    public final int STRICT             = 165;
270.1031 +
270.1032 +    /*
270.1033 +     * Punctuation
270.1034 +     */
270.1035 +    public final int SEMICOLON  = 135;
270.1036 +    public final int COLON              = 136;
270.1037 +    public final int QUESTIONMARK       = 137;
270.1038 +    public final int LBRACE             = 138;
270.1039 +    public final int RBRACE             = 139;
270.1040 +    public final int LPAREN             = 140;
270.1041 +    public final int RPAREN             = 141;
270.1042 +    public final int LSQBRACKET = 142;
270.1043 +    public final int RSQBRACKET = 143;
270.1044 +    public final int THROWS     = 144;
270.1045 +
270.1046 +    /*
270.1047 +     * Special tokens
270.1048 +     */
270.1049 +    public final int ERROR              = 145;          // an error
270.1050 +    public final int COMMENT    = 146;          // not used anymore.
270.1051 +    public final int TYPE               = 147;
270.1052 +    public final int LENGTH             = 148;
270.1053 +    public final int INLINERETURN       = 149;
270.1054 +    public final int INLINEMETHOD       = 150;
270.1055 +    public final int INLINENEWINSTANCE  = 151;
270.1056 +
270.1057 +    /*
270.1058 +     * Added for jasm
270.1059 +     */
270.1060 +        public final int METHODREF      = 152;
270.1061 +        public final int FIELDREF       = 153;
270.1062 +    public final int STACK              = 154;
270.1063 +    public final int LOCAL              = 155;
270.1064 +    public final int CPINDEX    = 156;
270.1065 +    public final int CPNAME             = 157;
270.1066 +    public final int SIGN               = 158;
270.1067 +    public final int BITS               = 159;
270.1068 +    public final int INF                = 160;
270.1069 +    public final int NAN                = 161;
270.1070 +    public final int INNERCLASS = 162;
270.1071 +    public final int OF         = 163;
270.1072 +    public final int SYNTHETIC          = 164;
270.1073 +// last used=165;
270.1074 +
270.1075 +   /*
270.1076 +     * Operator precedence
270.1077 +     */
270.1078 +    public static final int opPrecedence[] = {
270.1079 +        10,     11,     11,     11,     11,     11,     11,     11,     11,     11,
270.1080 +        11,     11,     11,     12,     13,     14,     15,     16,     17,     18,
270.1081 +        18,     19,     19,     19,     19,     19,     20,     20,     20,     21,
270.1082 +        21,     22,     22,     22,     23,     24,     24,     24,     24,     24,
270.1083 +        24,     25,     25,     26,     26,     26,     26,     26,     26
270.1084 +    };
270.1085 +
270.1086 +    /*
270.1087 +     * Operator names
270.1088 +     */
270.1089 +    public static final String opNames[] = {
270.1090 +        ",",            "=",            "*=",           "/=",           "%=",
270.1091 +        "+=",           "-=",           "<<=",          ">>=",          "<<<=",
270.1092 +        "&=",           "|=",           "^=",           "?:",           "||",
270.1093 +        "&&",           "|",            "^",            "&",            "!=",
270.1094 +        "==",           ">=",           ">",            "<=",           "<",
270.1095 +        "instanceof",   "<<",           ">>",           "<<<",          "+",
270.1096 +        "-",            "/",            "%",            "*",            "cast",
270.1097 +        "+",            "-",            "!",            "~",            "++",
270.1098 +        "--",           "new",          "new",          "new",          "++",
270.1099 +        "--",           "field",        "method",       "[]",           "new",
270.1100 +        "++",           "--",           null,           null,           null,
270.1101 +
270.1102 +        "convert",      "expr",         "array",        "goto",         null,
270.1103 +
270.1104 +        "Identifier",   "Boolean",      "Byte",         "Char",         "Short",
270.1105 +        "Integer",              "Long",         "Float",        "Double",       "String",
270.1106 +
270.1107 +        "byte",         "char",         "short",        "int",          "long",
270.1108 +        "float",        "double",       "void",         "boolean",      null,
270.1109 +
270.1110 +        "true",         "false",        "this",         "super",        "null",
270.1111 +        null,           null,           null,           null,           null,
270.1112 +
270.1113 +        "if",           "else",         "for",          "while",        "do",
270.1114 +        "switch",       "case",         "default",      "break",        "continue",
270.1115 +        "return",       "try",          "catch",        "finally",      "throw",
270.1116 +        "stat",         "expression",   "declaration",  "declaration",  null,
270.1117 +
270.1118 +        "import",       "class",        "extends",      "implements",   "interface",
270.1119 +        "package",      null,           null,           null,           null,
270.1120 +
270.1121 +        "private",      "public",       "protected",    "const",        "static",
270.1122 +        "transient",    "synchronized", "native",       "final",        "volatile",
270.1123 +        "abstract",     null,           null,           null,           null,
270.1124 +
270.1125 +        ";",            ":",            "?",            "{",            "}",
270.1126 +        "(",            ")",            "[",            "]",            "throws",
270.1127 +        "error",        "comment",      "type",         "length",       "inline-return",
270.1128 +        "inline-method", "inline-new",
270.1129 +        "method", "field", "stack", "locals", "CPINDEX", "CPName", "SIGN",
270.1130 +        "bits", "INF", "NaN", "InnerClass", "of", "synthetic"
270.1131 +    };
270.1132 +    
270.1133 +    static class AnnotationParser {
270.1134 +
270.1135 +        private final boolean textual;
270.1136 +        private final boolean iterateArray;
270.1137 +
270.1138 +        protected AnnotationParser(boolean textual, boolean iterateArray) {
270.1139 +            this.textual = textual;
270.1140 +            this.iterateArray = iterateArray;
270.1141 +        }
270.1142 +
270.1143 +        protected void visitAnnotationStart(String type, boolean top) throws IOException {
270.1144 +        }
270.1145 +
270.1146 +        protected void visitAnnotationEnd(String type, boolean top) throws IOException {
270.1147 +        }
270.1148 +
270.1149 +        protected void visitValueStart(String attrName, char type) throws IOException {
270.1150 +        }
270.1151 +
270.1152 +        protected void visitValueEnd(String attrName, char type) throws IOException {
270.1153 +        }
270.1154 +
270.1155 +        protected void visitAttr(
270.1156 +            String annoType, String attr, String attrType, String value) throws IOException {
270.1157 +        }
270.1158 +
270.1159 +        protected void visitEnumAttr(
270.1160 +            String annoType, String attr, String attrType, String value) throws IOException {
270.1161 +            visitAttr(annoType, attr, attrType, value);
270.1162 +        }
270.1163 +
270.1164 +        /**
270.1165 +         * Initialize the parsing with constant pool from
270.1166 +         * <code>cd</code>.
270.1167 +         *
270.1168 +         * @param attr the attribute defining annotations
270.1169 +         * @param cd constant pool
270.1170 +         * @throws IOException in case I/O fails
270.1171 +         */
270.1172 +        public final void parse(byte[] attr, ClassData cd) throws IOException {
270.1173 +            ByteArrayInputStream is = new ByteArrayInputStream(attr);
270.1174 +            DataInputStream dis = new DataInputStream(is);
270.1175 +            try {
270.1176 +                read(dis, cd);
270.1177 +            } finally {
270.1178 +                is.close();
270.1179 +            }
270.1180 +        }
270.1181 +
270.1182 +        private void read(DataInputStream dis, ClassData cd) throws IOException {
270.1183 +            int cnt = dis.readUnsignedShort();
270.1184 +            for (int i = 0; i < cnt; i++) {
270.1185 +                readAnno(dis, cd, true);
270.1186 +            }
270.1187 +        }
270.1188 +
270.1189 +        private void readAnno(DataInputStream dis, ClassData cd, boolean top) throws IOException {
270.1190 +            int type = dis.readUnsignedShort();
270.1191 +            String typeName = cd.StringValue(type);
270.1192 +            visitAnnotationStart(typeName, top);
270.1193 +            int cnt = dis.readUnsignedShort();
270.1194 +            for (int i = 0; i < cnt; i++) {
270.1195 +                String attrName = cd.StringValue(dis.readUnsignedShort());
270.1196 +                readValue(dis, cd, typeName, attrName);
270.1197 +            }
270.1198 +            visitAnnotationEnd(typeName, top);
270.1199 +            if (cnt == 0) {
270.1200 +                visitAttr(typeName, null, null, null);
270.1201 +            }
270.1202 +        }
270.1203 +
270.1204 +        private void readValue(
270.1205 +            DataInputStream dis, ClassData cd, String typeName, String attrName) throws IOException {
270.1206 +            char type = (char) dis.readByte();
270.1207 +            visitValueStart(attrName, type);
270.1208 +            if (type == '@') {
270.1209 +                readAnno(dis, cd, false);
270.1210 +            } else if ("CFJZsSIDB".indexOf(type) >= 0) { // NOI18N
270.1211 +                int primitive = dis.readUnsignedShort();
270.1212 +                String val = cd.stringValue(primitive, textual);
270.1213 +                String attrType;
270.1214 +                if (type == 's') {
270.1215 +                    attrType = "Ljava_lang_String_2";
270.1216 +                    if (textual) {
270.1217 +                        val = '"' + val + '"';
270.1218 +                    }
270.1219 +                } else {
270.1220 +                    attrType = "" + type;
270.1221 +                }
270.1222 +                visitAttr(typeName, attrName, attrType, val);
270.1223 +            } else if (type == 'c') {
270.1224 +                int cls = dis.readUnsignedShort();
270.1225 +            } else if (type == '[') {
270.1226 +                int cnt = dis.readUnsignedShort();
270.1227 +                for (int i = 0; i < cnt; i++) {
270.1228 +                    readValue(dis, cd, typeName, iterateArray ? attrName : null);
270.1229 +                }
270.1230 +            } else if (type == 'e') {
270.1231 +                int enumT = dis.readUnsignedShort();
270.1232 +                String attrType = cd.stringValue(enumT, textual);
270.1233 +                int enumN = dis.readUnsignedShort();
270.1234 +                String val = cd.stringValue(enumN, textual);
270.1235 +                visitEnumAttr(typeName, attrName, attrType, val);
270.1236 +            } else {
270.1237 +                throw new IOException("Unknown type " + type);
270.1238 +            }
270.1239 +            visitValueEnd(attrName, type);
270.1240 +        }
270.1241 +    }
270.1242 +    
270.1243 +    /**
270.1244 +     * Reads and stores attribute information.
270.1245 +     *
270.1246 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.1247 +     */
270.1248 +    private static class AttrData {
270.1249 +
270.1250 +        ClassData cls;
270.1251 +        int name_cpx;
270.1252 +        int datalen;
270.1253 +        byte data[];
270.1254 +
270.1255 +        public AttrData(ClassData cls) {
270.1256 +            this.cls = cls;
270.1257 +        }
270.1258 +
270.1259 +        /**
270.1260 +         * Reads unknown attribute.
270.1261 +         */
270.1262 +        public void read(int name_cpx, DataInputStream in) throws IOException {
270.1263 +            this.name_cpx = name_cpx;
270.1264 +            datalen = in.readInt();
270.1265 +            data = new byte[datalen];
270.1266 +            in.readFully(data);
270.1267 +        }
270.1268 +
270.1269 +        /**
270.1270 +         * Reads just the name of known attribute.
270.1271 +         */
270.1272 +        public void read(int name_cpx) {
270.1273 +            this.name_cpx = name_cpx;
270.1274 +        }
270.1275 +
270.1276 +        /**
270.1277 +         * Returns attribute name.
270.1278 +         */
270.1279 +        public String getAttrName() {
270.1280 +            return cls.getString(name_cpx);
270.1281 +        }
270.1282 +
270.1283 +        /**
270.1284 +         * Returns attribute data.
270.1285 +         */
270.1286 +        public byte[] getData() {
270.1287 +            return data;
270.1288 +        }
270.1289 +    }
270.1290 +
270.1291 +    /**
270.1292 +     * Stores constant pool entry information with one field.
270.1293 +     *
270.1294 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.1295 +     */
270.1296 +    private static class CPX {
270.1297 +
270.1298 +        int cpx;
270.1299 +
270.1300 +        CPX(int cpx) {
270.1301 +            this.cpx = cpx;
270.1302 +        }
270.1303 +    }
270.1304 +
270.1305 +    /**
270.1306 +     * Stores constant pool entry information with two fields.
270.1307 +     *
270.1308 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.1309 +     */
270.1310 +    private static class CPX2 {
270.1311 +
270.1312 +        int cpx1, cpx2;
270.1313 +
270.1314 +        CPX2(int cpx1, int cpx2) {
270.1315 +            this.cpx1 = cpx1;
270.1316 +            this.cpx2 = cpx2;
270.1317 +        }
270.1318 +    }
270.1319 +
270.1320 +    /**
270.1321 +     * Central data repository of the Java Disassembler. Stores all the
270.1322 +     * information in java class file.
270.1323 +     *
270.1324 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.1325 +     */
270.1326 +    static final class ClassData {
270.1327 +
270.1328 +        private int magic;
270.1329 +        private int minor_version;
270.1330 +        private int major_version;
270.1331 +        private int cpool_count;
270.1332 +        private Object cpool[];
270.1333 +        private int access;
270.1334 +        private int this_class = 0;
270.1335 +        private int super_class;
270.1336 +        private int interfaces_count;
270.1337 +        private int[] interfaces = new int[0];
270.1338 +        private int fields_count;
270.1339 +        private FieldData[] fields;
270.1340 +        private int methods_count;
270.1341 +        private MethodData[] methods;
270.1342 +        private InnerClassData[] innerClasses;
270.1343 +        private int attributes_count;
270.1344 +        private AttrData[] attrs;
270.1345 +        private String classname;
270.1346 +        private String superclassname;
270.1347 +        private int source_cpx = 0;
270.1348 +        private byte tags[];
270.1349 +        private Hashtable indexHashAscii = new Hashtable();
270.1350 +        private String pkgPrefix = "";
270.1351 +        private int pkgPrefixLen = 0;
270.1352 +
270.1353 +        /**
270.1354 +         * Read classfile to disassemble.
270.1355 +         */
270.1356 +        public ClassData(InputStream infile) throws IOException {
270.1357 +            this.read(new DataInputStream(infile));
270.1358 +        }
270.1359 +
270.1360 +        /**
270.1361 +         * Reads and stores class file information.
270.1362 +         */
270.1363 +        public void read(DataInputStream in) throws IOException {
270.1364 +            // Read the header
270.1365 +            magic = in.readInt();
270.1366 +            if (magic != JAVA_MAGIC) {
270.1367 +                throw new ClassFormatError("wrong magic: "
270.1368 +                    + toHex(magic) + ", expected "
270.1369 +                    + toHex(JAVA_MAGIC));
270.1370 +            }
270.1371 +            minor_version = in.readShort();
270.1372 +            major_version = in.readShort();
270.1373 +            if (major_version != JAVA_VERSION) {
270.1374 +            }
270.1375 +
270.1376 +            // Read the constant pool
270.1377 +            readCP(in);
270.1378 +            access = in.readUnsignedShort();
270.1379 +            this_class = in.readUnsignedShort();
270.1380 +            super_class = in.readUnsignedShort();
270.1381 +
270.1382 +            //Read interfaces.
270.1383 +            interfaces_count = in.readUnsignedShort();
270.1384 +            if (interfaces_count > 0) {
270.1385 +                interfaces = new int[interfaces_count];
270.1386 +            }
270.1387 +            for (int i = 0; i < interfaces_count; i++) {
270.1388 +                interfaces[i] = in.readShort();
270.1389 +            }
270.1390 +
270.1391 +            // Read the fields
270.1392 +            readFields(in);
270.1393 +
270.1394 +            // Read the methods
270.1395 +            readMethods(in);
270.1396 +
270.1397 +            // Read the attributes
270.1398 +            attributes_count = in.readUnsignedShort();
270.1399 +            attrs = new AttrData[attributes_count];
270.1400 +            for (int k = 0; k < attributes_count; k++) {
270.1401 +                int name_cpx = in.readUnsignedShort();
270.1402 +                if (getTag(name_cpx) == CONSTANT_UTF8
270.1403 +                    && getString(name_cpx).equals("SourceFile")) {
270.1404 +                    if (in.readInt() != 2) {
270.1405 +                        throw new ClassFormatError("invalid attr length");
270.1406 +                    }
270.1407 +                    source_cpx = in.readUnsignedShort();
270.1408 +                    AttrData attr = new AttrData(this);
270.1409 +                    attr.read(name_cpx);
270.1410 +                    attrs[k] = attr;
270.1411 +
270.1412 +                } else if (getTag(name_cpx) == CONSTANT_UTF8
270.1413 +                    && getString(name_cpx).equals("InnerClasses")) {
270.1414 +                    int length = in.readInt();
270.1415 +                    int num = in.readUnsignedShort();
270.1416 +                    if (2 + num * 8 != length) {
270.1417 +                        throw new ClassFormatError("invalid attr length");
270.1418 +                    }
270.1419 +                    innerClasses = new InnerClassData[num];
270.1420 +                    for (int j = 0; j < num; j++) {
270.1421 +                        InnerClassData innerClass = new InnerClassData(this);
270.1422 +                        innerClass.read(in);
270.1423 +                        innerClasses[j] = innerClass;
270.1424 +                    }
270.1425 +                    AttrData attr = new AttrData(this);
270.1426 +                    attr.read(name_cpx);
270.1427 +                    attrs[k] = attr;
270.1428 +                } else {
270.1429 +                    AttrData attr = new AttrData(this);
270.1430 +                    attr.read(name_cpx, in);
270.1431 +                    attrs[k] = attr;
270.1432 +                }
270.1433 +            }
270.1434 +            in.close();
270.1435 +        } // end ClassData.read()
270.1436 +
270.1437 +        /**
270.1438 +         * Reads and stores constant pool info.
270.1439 +         */
270.1440 +        void readCP(DataInputStream in) throws IOException {
270.1441 +            cpool_count = in.readUnsignedShort();
270.1442 +            tags = new byte[cpool_count];
270.1443 +            cpool = new Object[cpool_count];
270.1444 +            for (int i = 1; i < cpool_count; i++) {
270.1445 +                byte tag = in.readByte();
270.1446 +
270.1447 +                switch (tags[i] = tag) {
270.1448 +                    case CONSTANT_UTF8:
270.1449 +                        String str = in.readUTF();
270.1450 +                        indexHashAscii.put(cpool[i] = str, new Integer(i));
270.1451 +                        break;
270.1452 +                    case CONSTANT_INTEGER:
270.1453 +                        cpool[i] = new Integer(in.readInt());
270.1454 +                        break;
270.1455 +                    case CONSTANT_FLOAT:
270.1456 +                        cpool[i] = new Float(in.readFloat());
270.1457 +                        break;
270.1458 +                    case CONSTANT_LONG:
270.1459 +                        cpool[i++] = new Long(in.readLong());
270.1460 +                        break;
270.1461 +                    case CONSTANT_DOUBLE:
270.1462 +                        cpool[i++] = new Double(in.readDouble());
270.1463 +                        break;
270.1464 +                    case CONSTANT_CLASS:
270.1465 +                    case CONSTANT_STRING:
270.1466 +                        cpool[i] = new CPX(in.readUnsignedShort());
270.1467 +                        break;
270.1468 +
270.1469 +                    case CONSTANT_FIELD:
270.1470 +                    case CONSTANT_METHOD:
270.1471 +                    case CONSTANT_INTERFACEMETHOD:
270.1472 +                    case CONSTANT_NAMEANDTYPE:
270.1473 +                        cpool[i] = new CPX2(in.readUnsignedShort(), in.readUnsignedShort());
270.1474 +                        break;
270.1475 +
270.1476 +                    case 0:
270.1477 +                    default:
270.1478 +                        throw new ClassFormatError("invalid constant type: " + (int) tags[i]);
270.1479 +                }
270.1480 +            }
270.1481 +        }
270.1482 +
270.1483 +        /**
270.1484 +         * Reads and strores field info.
270.1485 +         */
270.1486 +        protected void readFields(DataInputStream in) throws IOException {
270.1487 +            int fields_count = in.readUnsignedShort();
270.1488 +            fields = new FieldData[fields_count];
270.1489 +            for (int k = 0; k < fields_count; k++) {
270.1490 +                FieldData field = new FieldData(this);
270.1491 +                field.read(in);
270.1492 +                fields[k] = field;
270.1493 +            }
270.1494 +        }
270.1495 +
270.1496 +        /**
270.1497 +         * Reads and strores Method info.
270.1498 +         */
270.1499 +        protected void readMethods(DataInputStream in) throws IOException {
270.1500 +            int methods_count = in.readUnsignedShort();
270.1501 +            methods = new MethodData[methods_count];
270.1502 +            for (int k = 0; k < methods_count; k++) {
270.1503 +                MethodData method = new MethodData(this);
270.1504 +                method.read(in);
270.1505 +                methods[k] = method;
270.1506 +            }
270.1507 +        }
270.1508 +
270.1509 +        /**
270.1510 +         * get a string
270.1511 +         */
270.1512 +        public String getString(int n) {
270.1513 +            if (n == 0) {
270.1514 +                return null;
270.1515 +            } else {
270.1516 +                return (String) cpool[n];
270.1517 +            }
270.1518 +        }
270.1519 +
270.1520 +        /**
270.1521 +         * get the type of constant given an index
270.1522 +         */
270.1523 +        public byte getTag(int n) {
270.1524 +            try {
270.1525 +                return tags[n];
270.1526 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1527 +                return (byte) 100;
270.1528 +            }
270.1529 +        }
270.1530 +        static final String hexString = "0123456789ABCDEF";
270.1531 +        public static char hexTable[] = hexString.toCharArray();
270.1532 +
270.1533 +        static String toHex(long val, int width) {
270.1534 +            StringBuffer s = new StringBuffer();
270.1535 +            for (int i = width - 1; i >= 0; i--) {
270.1536 +                s.append(hexTable[((int) (val >> (4 * i))) & 0xF]);
270.1537 +            }
270.1538 +            return "0x" + s.toString();
270.1539 +        }
270.1540 +
270.1541 +        static String toHex(long val) {
270.1542 +            int width;
270.1543 +            for (width = 16; width > 0; width--) {
270.1544 +                if ((val >> (width - 1) * 4) != 0) {
270.1545 +                    break;
270.1546 +                }
270.1547 +            }
270.1548 +            return toHex(val, width);
270.1549 +        }
270.1550 +
270.1551 +        static String toHex(int val) {
270.1552 +            int width;
270.1553 +            for (width = 8; width > 0; width--) {
270.1554 +                if ((val >> (width - 1) * 4) != 0) {
270.1555 +                    break;
270.1556 +                }
270.1557 +            }
270.1558 +            return toHex(val, width);
270.1559 +        }
270.1560 +
270.1561 +        /**
270.1562 +         * Returns the name of this class.
270.1563 +         */
270.1564 +        public String getClassName() {
270.1565 +            String res = null;
270.1566 +            if (this_class == 0) {
270.1567 +                return res;
270.1568 +            }
270.1569 +            int tcpx;
270.1570 +            try {
270.1571 +                if (tags[this_class] != CONSTANT_CLASS) {
270.1572 +                    return res; //"<CP["+cpx+"] is not a Class> ";
270.1573 +                }
270.1574 +                tcpx = ((CPX) cpool[this_class]).cpx;
270.1575 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1576 +                return res; // "#"+cpx+"// invalid constant pool index";
270.1577 +            } catch (Throwable e) {
270.1578 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1579 +            }
270.1580 +
270.1581 +            try {
270.1582 +                return (String) (cpool[tcpx]);
270.1583 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1584 +                return res; // "class #"+scpx+"// invalid constant pool index";
270.1585 +            } catch (ClassCastException e) {
270.1586 +                return res; // "class #"+scpx+"// invalid constant pool reference";
270.1587 +            } catch (Throwable e) {
270.1588 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1589 +            }
270.1590 +
270.1591 +        }
270.1592 +
270.1593 +        /**
270.1594 +         * Returns the name of class at perticular index.
270.1595 +         */
270.1596 +        public String getClassName(int cpx) {
270.1597 +            String res = "#" + cpx;
270.1598 +            if (cpx == 0) {
270.1599 +                return res;
270.1600 +            }
270.1601 +            int scpx;
270.1602 +            try {
270.1603 +                if (tags[cpx] != CONSTANT_CLASS) {
270.1604 +                    return res; //"<CP["+cpx+"] is not a Class> ";
270.1605 +                }
270.1606 +                scpx = ((CPX) cpool[cpx]).cpx;
270.1607 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1608 +                return res; // "#"+cpx+"// invalid constant pool index";
270.1609 +            } catch (Throwable e) {
270.1610 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1611 +            }
270.1612 +            res = "#" + scpx;
270.1613 +            try {
270.1614 +                return (String) (cpool[scpx]);
270.1615 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1616 +                return res; // "class #"+scpx+"// invalid constant pool index";
270.1617 +            } catch (ClassCastException e) {
270.1618 +                return res; // "class #"+scpx+"// invalid constant pool reference";
270.1619 +            } catch (Throwable e) {
270.1620 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1621 +            }
270.1622 +        }
270.1623 +
270.1624 +        public int getAccessFlags() {
270.1625 +            return access;
270.1626 +        }
270.1627 +
270.1628 +        /**
270.1629 +         * Returns true if it is a class
270.1630 +         */
270.1631 +        public boolean isClass() {
270.1632 +            if ((access & ACC_INTERFACE) == 0) {
270.1633 +                return true;
270.1634 +            }
270.1635 +            return false;
270.1636 +        }
270.1637 +
270.1638 +        /**
270.1639 +         * Returns true if it is a interface.
270.1640 +         */
270.1641 +        public boolean isInterface() {
270.1642 +            if ((access & ACC_INTERFACE) != 0) {
270.1643 +                return true;
270.1644 +            }
270.1645 +            return false;
270.1646 +        }
270.1647 +
270.1648 +        /**
270.1649 +         * Returns true if this member is public, false otherwise.
270.1650 +         */
270.1651 +        public boolean isPublic() {
270.1652 +            return (access & ACC_PUBLIC) != 0;
270.1653 +        }
270.1654 +
270.1655 +        /**
270.1656 +         * Returns the access of this class or interface.
270.1657 +         */
270.1658 +        public String[] getAccess() {
270.1659 +            Vector v = new Vector();
270.1660 +            if ((access & ACC_PUBLIC) != 0) {
270.1661 +                v.addElement("public");
270.1662 +            }
270.1663 +            if ((access & ACC_FINAL) != 0) {
270.1664 +                v.addElement("final");
270.1665 +            }
270.1666 +            if ((access & ACC_ABSTRACT) != 0) {
270.1667 +                v.addElement("abstract");
270.1668 +            }
270.1669 +            String[] accflags = new String[v.size()];
270.1670 +            v.copyInto(accflags);
270.1671 +            return accflags;
270.1672 +        }
270.1673 +
270.1674 +        /**
270.1675 +         * Returns list of innerclasses.
270.1676 +         */
270.1677 +        public InnerClassData[] getInnerClasses() {
270.1678 +            return innerClasses;
270.1679 +        }
270.1680 +
270.1681 +        /**
270.1682 +         * Returns list of attributes.
270.1683 +         */
270.1684 +        final AttrData[] getAttributes() {
270.1685 +            return attrs;
270.1686 +        }
270.1687 +
270.1688 +        public byte[] findAnnotationData(boolean classRetention) {
270.1689 +            String n = classRetention
270.1690 +                ? "RuntimeInvisibleAnnotations" : // NOI18N
270.1691 +                "RuntimeVisibleAnnotations"; // NOI18N
270.1692 +            return findAttr(n, attrs);
270.1693 +        }
270.1694 +
270.1695 +        /**
270.1696 +         * Returns true if superbit is set.
270.1697 +         */
270.1698 +        public boolean isSuperSet() {
270.1699 +            if ((access & ACC_SUPER) != 0) {
270.1700 +                return true;
270.1701 +            }
270.1702 +            return false;
270.1703 +        }
270.1704 +
270.1705 +        /**
270.1706 +         * Returns super class name.
270.1707 +         */
270.1708 +        public String getSuperClassName() {
270.1709 +            String res = null;
270.1710 +            if (super_class == 0) {
270.1711 +                return res;
270.1712 +            }
270.1713 +            int scpx;
270.1714 +            try {
270.1715 +                if (tags[super_class] != CONSTANT_CLASS) {
270.1716 +                    return res; //"<CP["+cpx+"] is not a Class> ";
270.1717 +                }
270.1718 +                scpx = ((CPX) cpool[super_class]).cpx;
270.1719 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1720 +                return res; // "#"+cpx+"// invalid constant pool index";
270.1721 +            } catch (Throwable e) {
270.1722 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1723 +            }
270.1724 +
270.1725 +            try {
270.1726 +                return (String) (cpool[scpx]);
270.1727 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1728 +                return res; // "class #"+scpx+"// invalid constant pool index";
270.1729 +            } catch (ClassCastException e) {
270.1730 +                return res; // "class #"+scpx+"// invalid constant pool reference";
270.1731 +            } catch (Throwable e) {
270.1732 +                return res; // "#"+cpx+"// ERROR IN DISASSEMBLER";
270.1733 +            }
270.1734 +        }
270.1735 +
270.1736 +        /**
270.1737 +         * Returns list of super interfaces.
270.1738 +         */
270.1739 +        public String[] getSuperInterfaces() {
270.1740 +            String interfacenames[] = new String[interfaces.length];
270.1741 +            int interfacecpx = -1;
270.1742 +            for (int i = 0; i < interfaces.length; i++) {
270.1743 +                interfacecpx = ((CPX) cpool[interfaces[i]]).cpx;
270.1744 +                interfacenames[i] = (String) (cpool[interfacecpx]);
270.1745 +            }
270.1746 +            return interfacenames;
270.1747 +        }
270.1748 +
270.1749 +        /**
270.1750 +         * Returns string at prticular constant pool index.
270.1751 +         */
270.1752 +        public String getStringValue(int cpoolx) {
270.1753 +            try {
270.1754 +                return ((String) cpool[cpoolx]);
270.1755 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1756 +                return "//invalid constant pool index:" + cpoolx;
270.1757 +            } catch (ClassCastException e) {
270.1758 +                return "//invalid constant pool ref:" + cpoolx;
270.1759 +            }
270.1760 +        }
270.1761 +
270.1762 +        /**
270.1763 +         * Returns list of field info.
270.1764 +         */
270.1765 +        public FieldData[] getFields() {
270.1766 +            return fields;
270.1767 +        }
270.1768 +
270.1769 +        /**
270.1770 +         * Returns list of method info.
270.1771 +         */
270.1772 +        public MethodData[] getMethods() {
270.1773 +            return methods;
270.1774 +        }
270.1775 +
270.1776 +        /**
270.1777 +         * Returns constant pool entry at that index.
270.1778 +         */
270.1779 +        public CPX2 getCpoolEntry(int cpx) {
270.1780 +            return ((CPX2) (cpool[cpx]));
270.1781 +        }
270.1782 +
270.1783 +        public Object getCpoolEntryobj(int cpx) {
270.1784 +            return (cpool[cpx]);
270.1785 +        }
270.1786 +
270.1787 +        /**
270.1788 +         * Returns index of this class.
270.1789 +         */
270.1790 +        public int getthis_cpx() {
270.1791 +            return this_class;
270.1792 +        }
270.1793 +
270.1794 +        /**
270.1795 +         * Returns string at that index.
270.1796 +         */
270.1797 +        public String StringValue(int cpx) {
270.1798 +            return stringValue(cpx, false);
270.1799 +        }
270.1800 +
270.1801 +        public String stringValue(int cpx, boolean textual) {
270.1802 +            return stringValue(cpx, textual, null);
270.1803 +        }
270.1804 +
270.1805 +        public String stringValue(int cpx, String[] classRefs) {
270.1806 +            return stringValue(cpx, true, classRefs);
270.1807 +        }
270.1808 +
270.1809 +        private String stringValue(int cpx, boolean textual, String[] refs) {
270.1810 +            if (cpx == 0) {
270.1811 +                return "#0";
270.1812 +            }
270.1813 +            int tag;
270.1814 +            Object x;
270.1815 +            String suffix = "";
270.1816 +            try {
270.1817 +                tag = tags[cpx];
270.1818 +                x = cpool[cpx];
270.1819 +            } catch (IndexOutOfBoundsException e) {
270.1820 +                return "<Incorrect CP index:" + cpx + ">";
270.1821 +            }
270.1822 +
270.1823 +            if (x == null) {
270.1824 +                return "<NULL>";
270.1825 +            }
270.1826 +            switch (tag) {
270.1827 +                case CONSTANT_UTF8: {
270.1828 +                    if (!textual) {
270.1829 +                        return (String) x;
270.1830 +                    }
270.1831 +                    StringBuilder sb = new StringBuilder();
270.1832 +                    String s = (String) x;
270.1833 +                    for (int k = 0; k < s.length(); k++) {
270.1834 +                        char c = s.charAt(k);
270.1835 +                        switch (c) {
270.1836 +                            case '\\':
270.1837 +                                sb.append('\\').append('\\');
270.1838 +                                break;
270.1839 +                            case '\t':
270.1840 +                                sb.append('\\').append('t');
270.1841 +                                break;
270.1842 +                            case '\n':
270.1843 +                                sb.append('\\').append('n');
270.1844 +                                break;
270.1845 +                            case '\r':
270.1846 +                                sb.append('\\').append('r');
270.1847 +                                break;
270.1848 +                            case '\"':
270.1849 +                                sb.append('\\').append('\"');
270.1850 +                                break;
270.1851 +                            default:
270.1852 +                                sb.append(c);
270.1853 +                        }
270.1854 +                    }
270.1855 +                    return sb.toString();
270.1856 +                }
270.1857 +                case CONSTANT_DOUBLE: {
270.1858 +                    Double d = (Double) x;
270.1859 +                    String sd = d.toString();
270.1860 +                    if (textual) {
270.1861 +                        return sd;
270.1862 +                    }
270.1863 +                    return sd + "d";
270.1864 +                }
270.1865 +                case CONSTANT_FLOAT: {
270.1866 +                    Float f = (Float) x;
270.1867 +                    String sf = (f).toString();
270.1868 +                    if (textual) {
270.1869 +                        return sf;
270.1870 +                    }
270.1871 +                    return sf + "f";
270.1872 +                }
270.1873 +                case CONSTANT_LONG: {
270.1874 +                    Long ln = (Long) x;
270.1875 +                    if (textual) {
270.1876 +                        return ln.toString();
270.1877 +                    }
270.1878 +                    return ln.toString() + 'l';
270.1879 +                }
270.1880 +                case CONSTANT_INTEGER: {
270.1881 +                    Integer in = (Integer) x;
270.1882 +                    return in.toString();
270.1883 +                }
270.1884 +                case CONSTANT_CLASS:
270.1885 +                    String jn = getClassName(cpx);
270.1886 +                    if (textual) {
270.1887 +                        if (refs != null) {
270.1888 +                            refs[0] = jn;
270.1889 +                        }
270.1890 +                        return jn;
270.1891 +                    }
270.1892 +                    return javaName(jn);
270.1893 +                case CONSTANT_STRING:
270.1894 +                    String sv = stringValue(((CPX) x).cpx, textual);
270.1895 +                    if (textual) {
270.1896 +                        return '"' + sv + '"';
270.1897 +                    } else {
270.1898 +                        return sv;
270.1899 +                    }
270.1900 +                case CONSTANT_FIELD:
270.1901 +                case CONSTANT_METHOD:
270.1902 +                case CONSTANT_INTERFACEMETHOD:
270.1903 +                    //return getShortClassName(((CPX2)x).cpx1)+"."+StringValue(((CPX2)x).cpx2);
270.1904 +                    return javaName(getClassName(((CPX2) x).cpx1)) + "." + StringValue(((CPX2) x).cpx2);
270.1905 +
270.1906 +                case CONSTANT_NAMEANDTYPE:
270.1907 +                    return getName(((CPX2) x).cpx1) + ":" + StringValue(((CPX2) x).cpx2);
270.1908 +                default:
270.1909 +                    return "UnknownTag"; //TBD
270.1910 +            }
270.1911 +        }
270.1912 +
270.1913 +        /**
270.1914 +         * Returns resolved java type name.
270.1915 +         */
270.1916 +        public String javaName(String name) {
270.1917 +            if (name == null) {
270.1918 +                return "null";
270.1919 +            }
270.1920 +            int len = name.length();
270.1921 +            if (len == 0) {
270.1922 +                return "\"\"";
270.1923 +            }
270.1924 +            int cc = '/';
270.1925 +            fullname:
270.1926 +            { // xxx/yyy/zzz
270.1927 +                int cp;
270.1928 +                for (int k = 0; k < len; k += Character.charCount(cp)) {
270.1929 +                    cp = name.codePointAt(k);
270.1930 +                    if (cc == '/') {
270.1931 +                        if (!isJavaIdentifierStart(cp)) {
270.1932 +                            break fullname;
270.1933 +                        }
270.1934 +                    } else if (cp != '/') {
270.1935 +                        if (!isJavaIdentifierPart(cp)) {
270.1936 +                            break fullname;
270.1937 +                        }
270.1938 +                    }
270.1939 +                    cc = cp;
270.1940 +                }
270.1941 +                return name;
270.1942 +            }
270.1943 +            return "\"" + name + "\"";
270.1944 +        }
270.1945 +
270.1946 +        public String getName(int cpx) {
270.1947 +            String res;
270.1948 +            try {
270.1949 +                return javaName((String) cpool[cpx]); //.replace('/','.');
270.1950 +            } catch (ArrayIndexOutOfBoundsException e) {
270.1951 +                return "<invalid constant pool index:" + cpx + ">";
270.1952 +            } catch (ClassCastException e) {
270.1953 +                return "<invalid constant pool ref:" + cpx + ">";
270.1954 +            }
270.1955 +        }
270.1956 +
270.1957 +        /**
270.1958 +         * Returns unqualified class name.
270.1959 +         */
270.1960 +        public String getShortClassName(int cpx) {
270.1961 +            String classname = javaName(getClassName(cpx));
270.1962 +            pkgPrefixLen = classname.lastIndexOf("/") + 1;
270.1963 +            if (pkgPrefixLen != 0) {
270.1964 +                pkgPrefix = classname.substring(0, pkgPrefixLen);
270.1965 +                if (classname.startsWith(pkgPrefix)) {
270.1966 +                    return classname.substring(pkgPrefixLen);
270.1967 +                }
270.1968 +            }
270.1969 +            return classname;
270.1970 +        }
270.1971 +
270.1972 +        /**
270.1973 +         * Returns source file name.
270.1974 +         */
270.1975 +        public String getSourceName() {
270.1976 +            return getName(source_cpx);
270.1977 +        }
270.1978 +
270.1979 +        /**
270.1980 +         * Returns package name.
270.1981 +         */
270.1982 +        public String getPkgName() {
270.1983 +            String classname = getClassName(this_class);
270.1984 +            pkgPrefixLen = classname.lastIndexOf("/") + 1;
270.1985 +            if (pkgPrefixLen != 0) {
270.1986 +                pkgPrefix = classname.substring(0, pkgPrefixLen);
270.1987 +                return ("package  " + pkgPrefix.substring(0, pkgPrefixLen - 1) + ";\n");
270.1988 +            } else {
270.1989 +                return null;
270.1990 +            }
270.1991 +        }
270.1992 +
270.1993 +        /**
270.1994 +         * Returns total constant pool entry count.
270.1995 +         */
270.1996 +        public int getCpoolCount() {
270.1997 +            return cpool_count;
270.1998 +        }
270.1999 +
270.2000 +        /**
270.2001 +         * Returns minor version of class file.
270.2002 +         */
270.2003 +        public int getMinor_version() {
270.2004 +            return minor_version;
270.2005 +        }
270.2006 +
270.2007 +        /**
270.2008 +         * Returns major version of class file.
270.2009 +         */
270.2010 +        public int getMajor_version() {
270.2011 +            return major_version;
270.2012 +        }
270.2013 +
270.2014 +        private boolean isJavaIdentifierStart(int cp) {
270.2015 +            return ('a' <= cp && cp <= 'z') || ('A' <= cp && cp <= 'Z');
270.2016 +        }
270.2017 +
270.2018 +        private boolean isJavaIdentifierPart(int cp) {
270.2019 +            return isJavaIdentifierStart(cp) || ('0' <= cp && cp <= '9');
270.2020 +        }
270.2021 +
270.2022 +        public String[] getNameAndType(int indx) {
270.2023 +            return getNameAndType(indx, 0, new String[2]);
270.2024 +        }
270.2025 +
270.2026 +        private String[] getNameAndType(int indx, int at, String[] arr) {
270.2027 +            CPX2 c2 = getCpoolEntry(indx);
270.2028 +            arr[at] = StringValue(c2.cpx1);
270.2029 +            arr[at + 1] = StringValue(c2.cpx2);
270.2030 +            return arr;
270.2031 +        }
270.2032 +
270.2033 +        public String[] getFieldInfoName(int indx) {
270.2034 +            CPX2 c2 = getCpoolEntry(indx);
270.2035 +            String[] arr = new String[3];
270.2036 +            arr[0] = getClassName(c2.cpx1);
270.2037 +            return getNameAndType(c2.cpx2, 1, arr);
270.2038 +        }
270.2039 +
270.2040 +        static byte[] findAttr(String n, AttrData[] attrs) {
270.2041 +            for (AttrData ad : attrs) {
270.2042 +                if (n.equals(ad.getAttrName())) {
270.2043 +                    return ad.getData();
270.2044 +                }
270.2045 +            }
270.2046 +            return null;
270.2047 +        }
270.2048 +    }
270.2049 +
270.2050 +    /**
270.2051 +     * Strores field data informastion.
270.2052 +     *
270.2053 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.2054 +     */
270.2055 +    static class FieldData {
270.2056 +
270.2057 +        ClassData cls;
270.2058 +        int access;
270.2059 +        int name_index;
270.2060 +        int descriptor_index;
270.2061 +        int attributes_count;
270.2062 +        int value_cpx = 0;
270.2063 +        boolean isSynthetic = false;
270.2064 +        boolean isDeprecated = false;
270.2065 +        Vector attrs;
270.2066 +
270.2067 +        public FieldData(ClassData cls) {
270.2068 +            this.cls = cls;
270.2069 +        }
270.2070 +
270.2071 +        /**
270.2072 +         * Read and store field info.
270.2073 +         */
270.2074 +        public void read(DataInputStream in) throws IOException {
270.2075 +            access = in.readUnsignedShort();
270.2076 +            name_index = in.readUnsignedShort();
270.2077 +            descriptor_index = in.readUnsignedShort();
270.2078 +            // Read the attributes
270.2079 +            int attributes_count = in.readUnsignedShort();
270.2080 +            attrs = new Vector(attributes_count);
270.2081 +            for (int i = 0; i < attributes_count; i++) {
270.2082 +                int attr_name_index = in.readUnsignedShort();
270.2083 +                if (cls.getTag(attr_name_index) != CONSTANT_UTF8) {
270.2084 +                    continue;
270.2085 +                }
270.2086 +                String attr_name = cls.getString(attr_name_index);
270.2087 +                if (attr_name.equals("ConstantValue")) {
270.2088 +                    if (in.readInt() != 2) {
270.2089 +                        throw new ClassFormatError("invalid ConstantValue attr length");
270.2090 +                    }
270.2091 +                    value_cpx = in.readUnsignedShort();
270.2092 +                    AttrData attr = new AttrData(cls);
270.2093 +                    attr.read(attr_name_index);
270.2094 +                    attrs.addElement(attr);
270.2095 +                } else if (attr_name.equals("Synthetic")) {
270.2096 +                    if (in.readInt() != 0) {
270.2097 +                        throw new ClassFormatError("invalid Synthetic attr length");
270.2098 +                    }
270.2099 +                    isSynthetic = true;
270.2100 +                    AttrData attr = new AttrData(cls);
270.2101 +                    attr.read(attr_name_index);
270.2102 +                    attrs.addElement(attr);
270.2103 +                } else if (attr_name.equals("Deprecated")) {
270.2104 +                    if (in.readInt() != 0) {
270.2105 +                        throw new ClassFormatError("invalid Synthetic attr length");
270.2106 +                    }
270.2107 +                    isDeprecated = true;
270.2108 +                    AttrData attr = new AttrData(cls);
270.2109 +                    attr.read(attr_name_index);
270.2110 +                    attrs.addElement(attr);
270.2111 +                } else {
270.2112 +                    AttrData attr = new AttrData(cls);
270.2113 +                    attr.read(attr_name_index, in);
270.2114 +                    attrs.addElement(attr);
270.2115 +                }
270.2116 +            }
270.2117 +
270.2118 +        }  // end read
270.2119 +
270.2120 +        public boolean isStatic() {
270.2121 +            return (access & ACC_STATIC) != 0;
270.2122 +        }
270.2123 +
270.2124 +        /**
270.2125 +         * Returns access of a field.
270.2126 +         */
270.2127 +        public String[] getAccess() {
270.2128 +            Vector v = new Vector();
270.2129 +            if ((access & ACC_PUBLIC) != 0) {
270.2130 +                v.addElement("public");
270.2131 +            }
270.2132 +            if ((access & ACC_PRIVATE) != 0) {
270.2133 +                v.addElement("private");
270.2134 +            }
270.2135 +            if ((access & ACC_PROTECTED) != 0) {
270.2136 +                v.addElement("protected");
270.2137 +            }
270.2138 +            if ((access & ACC_STATIC) != 0) {
270.2139 +                v.addElement("static");
270.2140 +            }
270.2141 +            if ((access & ACC_FINAL) != 0) {
270.2142 +                v.addElement("final");
270.2143 +            }
270.2144 +            if ((access & ACC_VOLATILE) != 0) {
270.2145 +                v.addElement("volatile");
270.2146 +            }
270.2147 +            if ((access & ACC_TRANSIENT) != 0) {
270.2148 +                v.addElement("transient");
270.2149 +            }
270.2150 +            String[] accflags = new String[v.size()];
270.2151 +            v.copyInto(accflags);
270.2152 +            return accflags;
270.2153 +        }
270.2154 +
270.2155 +        /**
270.2156 +         * Returns name of a field.
270.2157 +         */
270.2158 +        public String getName() {
270.2159 +            return cls.getStringValue(name_index);
270.2160 +        }
270.2161 +
270.2162 +        /**
270.2163 +         * Returns internal signature of a field
270.2164 +         */
270.2165 +        public String getInternalSig() {
270.2166 +            return cls.getStringValue(descriptor_index);
270.2167 +        }
270.2168 +
270.2169 +        /**
270.2170 +         * Returns true if field is synthetic.
270.2171 +         */
270.2172 +        public boolean isSynthetic() {
270.2173 +            return isSynthetic;
270.2174 +        }
270.2175 +
270.2176 +        /**
270.2177 +         * Returns true if field is deprecated.
270.2178 +         */
270.2179 +        public boolean isDeprecated() {
270.2180 +            return isDeprecated;
270.2181 +        }
270.2182 +
270.2183 +        /**
270.2184 +         * Returns index of constant value in cpool.
270.2185 +         */
270.2186 +        public int getConstantValueIndex() {
270.2187 +            return (value_cpx);
270.2188 +        }
270.2189 +
270.2190 +        /**
270.2191 +         * Returns list of attributes of field.
270.2192 +         */
270.2193 +        public Vector getAttributes() {
270.2194 +            return attrs;
270.2195 +        }
270.2196 +
270.2197 +        public byte[] findAnnotationData(boolean classRetention) {
270.2198 +            String n = classRetention
270.2199 +                ? "RuntimeInvisibleAnnotations" : // NOI18N
270.2200 +                "RuntimeVisibleAnnotations"; // NOI18N
270.2201 +            AttrData[] arr = new AttrData[attrs.size()];
270.2202 +            attrs.copyInto(arr);
270.2203 +            return ClassData.findAttr(n, arr);
270.2204 +        }
270.2205 +    }
270.2206 +
270.2207 +    /**
270.2208 +     * A JavaScript optimized replacement for Hashtable.
270.2209 +     *
270.2210 +     * @author Jaroslav Tulach <jtulach@netbeans.org>
270.2211 +     */
270.2212 +    private static final class Hashtable {
270.2213 +
270.2214 +        private Object[] keys;
270.2215 +        private Object[] values;
270.2216 +
270.2217 +        Hashtable(int i) {
270.2218 +            this();
270.2219 +        }
270.2220 +
270.2221 +        Hashtable(int i, double d) {
270.2222 +            this();
270.2223 +        }
270.2224 +
270.2225 +        Hashtable() {
270.2226 +        }
270.2227 +
270.2228 +        synchronized void put(Object key, Object val) {
270.2229 +            int[] where = {-1, -1};
270.2230 +            Object found = get(key, where);
270.2231 +            if (where[0] != -1) {
270.2232 +                // key exists
270.2233 +                values[where[0]] = val;
270.2234 +            } else {
270.2235 +                if (where[1] != -1) {
270.2236 +                    // null found
270.2237 +                    keys[where[1]] = key;
270.2238 +                    values[where[1]] = val;
270.2239 +                } else {
270.2240 +                    if (keys == null) {
270.2241 +                        keys = new Object[11];
270.2242 +                        values = new Object[11];
270.2243 +                        keys[0] = key;
270.2244 +                        values[0] = val;
270.2245 +                    } else {
270.2246 +                        Object[] newKeys = new Object[keys.length * 2];
270.2247 +                        Object[] newValues = new Object[values.length * 2];
270.2248 +                        for (int i = 0; i < keys.length; i++) {
270.2249 +                            newKeys[i] = keys[i];
270.2250 +                            newValues[i] = values[i];
270.2251 +                        }
270.2252 +                        newKeys[keys.length] = key;
270.2253 +                        newValues[keys.length] = val;
270.2254 +                        keys = newKeys;
270.2255 +                        values = newValues;
270.2256 +                    }
270.2257 +                }
270.2258 +            }
270.2259 +        }
270.2260 +
270.2261 +        Object get(Object key) {
270.2262 +            return get(key, null);
270.2263 +        }
270.2264 +
270.2265 +        private synchronized Object get(Object key, int[] foundAndNull) {
270.2266 +            if (keys == null) {
270.2267 +                return null;
270.2268 +            }
270.2269 +            for (int i = 0; i < keys.length; i++) {
270.2270 +                if (keys[i] == null) {
270.2271 +                    if (foundAndNull != null) {
270.2272 +                        foundAndNull[1] = i;
270.2273 +                    }
270.2274 +                } else if (keys[i].equals(key)) {
270.2275 +                    if (foundAndNull != null) {
270.2276 +                        foundAndNull[0] = i;
270.2277 +                    }
270.2278 +                    return values[i];
270.2279 +                }
270.2280 +            }
270.2281 +            return null;
270.2282 +        }
270.2283 +    }
270.2284 +
270.2285 +    /**
270.2286 +     * Strores InnerClass data informastion.
270.2287 +     *
270.2288 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.2289 +     */
270.2290 +    private static class InnerClassData {
270.2291 +
270.2292 +        ClassData cls;
270.2293 +        int inner_class_info_index, outer_class_info_index, inner_name_index, access;
270.2294 +
270.2295 +        public InnerClassData(ClassData cls) {
270.2296 +            this.cls = cls;
270.2297 +
270.2298 +        }
270.2299 +
270.2300 +        /**
270.2301 +         * Read Innerclass attribute data.
270.2302 +         */
270.2303 +        public void read(DataInputStream in) throws IOException {
270.2304 +            inner_class_info_index = in.readUnsignedShort();
270.2305 +            outer_class_info_index = in.readUnsignedShort();
270.2306 +            inner_name_index = in.readUnsignedShort();
270.2307 +            access = in.readUnsignedShort();
270.2308 +        }  // end read
270.2309 +
270.2310 +        /**
270.2311 +         * Returns the access of this class or interface.
270.2312 +         */
270.2313 +        public String[] getAccess() {
270.2314 +            Vector v = new Vector();
270.2315 +            if ((access & ACC_PUBLIC) != 0) {
270.2316 +                v.addElement("public");
270.2317 +            }
270.2318 +            if ((access & ACC_FINAL) != 0) {
270.2319 +                v.addElement("final");
270.2320 +            }
270.2321 +            if ((access & ACC_ABSTRACT) != 0) {
270.2322 +                v.addElement("abstract");
270.2323 +            }
270.2324 +            String[] accflags = new String[v.size()];
270.2325 +            v.copyInto(accflags);
270.2326 +            return accflags;
270.2327 +        }
270.2328 +    } // end InnerClassData
270.2329 +
270.2330 +    /**
270.2331 +     * Strores LineNumberTable data information.
270.2332 +     *
270.2333 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.2334 +     */
270.2335 +    private static class LineNumData {
270.2336 +
270.2337 +        short start_pc, line_number;
270.2338 +
270.2339 +        public LineNumData() {
270.2340 +        }
270.2341 +
270.2342 +        /**
270.2343 +         * Read LineNumberTable attribute.
270.2344 +         */
270.2345 +        public LineNumData(DataInputStream in) throws IOException {
270.2346 +            start_pc = in.readShort();
270.2347 +            line_number = in.readShort();
270.2348 +
270.2349 +        }
270.2350 +    }
270.2351 +
270.2352 +    /**
270.2353 +     * Strores LocalVariableTable data information.
270.2354 +     *
270.2355 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.2356 +     */
270.2357 +    private static class LocVarData {
270.2358 +
270.2359 +        short start_pc, length, name_cpx, sig_cpx, slot;
270.2360 +
270.2361 +        public LocVarData() {
270.2362 +        }
270.2363 +
270.2364 +        /**
270.2365 +         * Read LocalVariableTable attribute.
270.2366 +         */
270.2367 +        public LocVarData(DataInputStream in) throws IOException {
270.2368 +            start_pc = in.readShort();
270.2369 +            length = in.readShort();
270.2370 +            name_cpx = in.readShort();
270.2371 +            sig_cpx = in.readShort();
270.2372 +            slot = in.readShort();
270.2373 +
270.2374 +        }
270.2375 +    }
270.2376 +    /**
270.2377 +     * Strores method data informastion.
270.2378 +     *
270.2379 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.2380 +     */
270.2381 +    static class MethodData {
270.2382 +
270.2383 +        ClassData cls;
270.2384 +        int access;
270.2385 +        int name_index;
270.2386 +        int descriptor_index;
270.2387 +        int attributes_count;
270.2388 +        byte[] code;
270.2389 +        Vector exception_table = new Vector(0);
270.2390 +        Vector lin_num_tb = new Vector(0);
270.2391 +        Vector loc_var_tb = new Vector(0);
270.2392 +        StackMapTableData[] stackMapTable;
270.2393 +        StackMapData[] stackMap;
270.2394 +        int[] exc_index_table = null;
270.2395 +        Vector attrs = new Vector(0);
270.2396 +        Vector code_attrs = new Vector(0);
270.2397 +        int max_stack, max_locals;
270.2398 +        boolean isSynthetic = false;
270.2399 +        boolean isDeprecated = false;
270.2400 +
270.2401 +        public MethodData(ClassData cls) {
270.2402 +            this.cls = cls;
270.2403 +        }
270.2404 +
270.2405 +        /**
270.2406 +         * Read method info.
270.2407 +         */
270.2408 +        public void read(DataInputStream in) throws IOException {
270.2409 +            access = in.readUnsignedShort();
270.2410 +            name_index = in.readUnsignedShort();
270.2411 +            descriptor_index = in.readUnsignedShort();
270.2412 +            int attributes_count = in.readUnsignedShort();
270.2413 +            for (int i = 0; i < attributes_count; i++) {
270.2414 +                int attr_name_index = in.readUnsignedShort();
270.2415 +
270.2416 +                readAttr:
270.2417 +                {
270.2418 +                    if (cls.getTag(attr_name_index) == CONSTANT_UTF8) {
270.2419 +                        String attr_name = cls.getString(attr_name_index);
270.2420 +                        if (attr_name.equals("Code")) {
270.2421 +                            readCode(in);
270.2422 +                            AttrData attr = new AttrData(cls);
270.2423 +                            attr.read(attr_name_index);
270.2424 +                            attrs.addElement(attr);
270.2425 +                            break readAttr;
270.2426 +                        } else if (attr_name.equals("Exceptions")) {
270.2427 +                            readExceptions(in);
270.2428 +                            AttrData attr = new AttrData(cls);
270.2429 +                            attr.read(attr_name_index);
270.2430 +                            attrs.addElement(attr);
270.2431 +                            break readAttr;
270.2432 +                        } else if (attr_name.equals("Synthetic")) {
270.2433 +                            if (in.readInt() != 0) {
270.2434 +                                throw new ClassFormatError("invalid Synthetic attr length");
270.2435 +                            }
270.2436 +                            isSynthetic = true;
270.2437 +                            AttrData attr = new AttrData(cls);
270.2438 +                            attr.read(attr_name_index);
270.2439 +                            attrs.addElement(attr);
270.2440 +                            break readAttr;
270.2441 +                        } else if (attr_name.equals("Deprecated")) {
270.2442 +                            if (in.readInt() != 0) {
270.2443 +                                throw new ClassFormatError("invalid Synthetic attr length");
270.2444 +                            }
270.2445 +                            isDeprecated = true;
270.2446 +                            AttrData attr = new AttrData(cls);
270.2447 +                            attr.read(attr_name_index);
270.2448 +                            attrs.addElement(attr);
270.2449 +                            break readAttr;
270.2450 +                        }
270.2451 +                    }
270.2452 +                    AttrData attr = new AttrData(cls);
270.2453 +                    attr.read(attr_name_index, in);
270.2454 +                    attrs.addElement(attr);
270.2455 +                }
270.2456 +            }
270.2457 +        }
270.2458 +
270.2459 +        /**
270.2460 +         * Read code attribute info.
270.2461 +         */
270.2462 +        public void readCode(DataInputStream in) throws IOException {
270.2463 +
270.2464 +            int attr_length = in.readInt();
270.2465 +            max_stack = in.readUnsignedShort();
270.2466 +            max_locals = in.readUnsignedShort();
270.2467 +            int codelen = in.readInt();
270.2468 +
270.2469 +            code = new byte[codelen];
270.2470 +            int totalread = 0;
270.2471 +            while (totalread < codelen) {
270.2472 +                totalread += in.read(code, totalread, codelen - totalread);
270.2473 +            }
270.2474 +            //      in.read(code, 0, codelen);
270.2475 +            int clen = 0;
270.2476 +            readExceptionTable(in);
270.2477 +            int code_attributes_count = in.readUnsignedShort();
270.2478 +
270.2479 +            for (int k = 0; k < code_attributes_count; k++) {
270.2480 +                int table_name_index = in.readUnsignedShort();
270.2481 +                int table_name_tag = cls.getTag(table_name_index);
270.2482 +                AttrData attr = new AttrData(cls);
270.2483 +                if (table_name_tag == CONSTANT_UTF8) {
270.2484 +                    String table_name_tstr = cls.getString(table_name_index);
270.2485 +                    if (table_name_tstr.equals("LineNumberTable")) {
270.2486 +                        readLineNumTable(in);
270.2487 +                        attr.read(table_name_index);
270.2488 +                    } else if (table_name_tstr.equals("LocalVariableTable")) {
270.2489 +                        readLocVarTable(in);
270.2490 +                        attr.read(table_name_index);
270.2491 +                    } else if (table_name_tstr.equals("StackMapTable")) {
270.2492 +                        readStackMapTable(in);
270.2493 +                        attr.read(table_name_index);
270.2494 +                    } else if (table_name_tstr.equals("StackMap")) {
270.2495 +                        readStackMap(in);
270.2496 +                        attr.read(table_name_index);
270.2497 +                    } else {
270.2498 +                        attr.read(table_name_index, in);
270.2499 +                    }
270.2500 +                    code_attrs.addElement(attr);
270.2501 +                    continue;
270.2502 +                }
270.2503 +
270.2504 +                attr.read(table_name_index, in);
270.2505 +                code_attrs.addElement(attr);
270.2506 +            }
270.2507 +        }
270.2508 +
270.2509 +        /**
270.2510 +         * Read exception table info.
270.2511 +         */
270.2512 +        void readExceptionTable(DataInputStream in) throws IOException {
270.2513 +            int exception_table_len = in.readUnsignedShort();
270.2514 +            exception_table = new Vector(exception_table_len);
270.2515 +            for (int l = 0; l < exception_table_len; l++) {
270.2516 +                exception_table.addElement(new TrapData(in, l));
270.2517 +            }
270.2518 +        }
270.2519 +
270.2520 +        /**
270.2521 +         * Read LineNumberTable attribute info.
270.2522 +         */
270.2523 +        void readLineNumTable(DataInputStream in) throws IOException {
270.2524 +            int attr_len = in.readInt(); // attr_length
270.2525 +            int lin_num_tb_len = in.readUnsignedShort();
270.2526 +            lin_num_tb = new Vector(lin_num_tb_len);
270.2527 +            for (int l = 0; l < lin_num_tb_len; l++) {
270.2528 +                lin_num_tb.addElement(new LineNumData(in));
270.2529 +            }
270.2530 +        }
270.2531 +
270.2532 +        /**
270.2533 +         * Read LocalVariableTable attribute info.
270.2534 +         */
270.2535 +        void readLocVarTable(DataInputStream in) throws IOException {
270.2536 +            int attr_len = in.readInt(); // attr_length
270.2537 +            int loc_var_tb_len = in.readUnsignedShort();
270.2538 +            loc_var_tb = new Vector(loc_var_tb_len);
270.2539 +            for (int l = 0; l < loc_var_tb_len; l++) {
270.2540 +                loc_var_tb.addElement(new LocVarData(in));
270.2541 +            }
270.2542 +        }
270.2543 +
270.2544 +        /**
270.2545 +         * Read Exception attribute info.
270.2546 +         */
270.2547 +        public void readExceptions(DataInputStream in) throws IOException {
270.2548 +            int attr_len = in.readInt(); // attr_length in prog
270.2549 +            int num_exceptions = in.readUnsignedShort();
270.2550 +            exc_index_table = new int[num_exceptions];
270.2551 +            for (int l = 0; l < num_exceptions; l++) {
270.2552 +                int exc = in.readShort();
270.2553 +                exc_index_table[l] = exc;
270.2554 +            }
270.2555 +        }
270.2556 +
270.2557 +        /**
270.2558 +         * Read StackMapTable attribute info.
270.2559 +         */
270.2560 +        void readStackMapTable(DataInputStream in) throws IOException {
270.2561 +            int attr_len = in.readInt();  //attr_length
270.2562 +            int stack_map_tb_len = in.readUnsignedShort();
270.2563 +            stackMapTable = new StackMapTableData[stack_map_tb_len];
270.2564 +            for (int i = 0; i < stack_map_tb_len; i++) {
270.2565 +                stackMapTable[i] = StackMapTableData.getInstance(in, this);
270.2566 +            }
270.2567 +        }
270.2568 +
270.2569 +        /**
270.2570 +         * Read StackMap attribute info.
270.2571 +         */
270.2572 +        void readStackMap(DataInputStream in) throws IOException {
270.2573 +            int attr_len = in.readInt();  //attr_length
270.2574 +            int stack_map_len = in.readUnsignedShort();
270.2575 +            stackMap = new StackMapData[stack_map_len];
270.2576 +            for (int i = 0; i < stack_map_len; i++) {
270.2577 +                stackMap[i] = new StackMapData(in, this);
270.2578 +            }
270.2579 +        }
270.2580 +
270.2581 +        /**
270.2582 +         * Return access of the method.
270.2583 +         */
270.2584 +        public int getAccess() {
270.2585 +            return access;
270.2586 +        }
270.2587 +
270.2588 +        /**
270.2589 +         * Return name of the method.
270.2590 +         */
270.2591 +        public String getName() {
270.2592 +            return cls.getStringValue(name_index);
270.2593 +        }
270.2594 +
270.2595 +        /**
270.2596 +         * Return internal siganature of the method.
270.2597 +         */
270.2598 +        public String getInternalSig() {
270.2599 +            return cls.getStringValue(descriptor_index);
270.2600 +        }
270.2601 +
270.2602 +        /**
270.2603 +         * Return code attribute data of a method.
270.2604 +         */
270.2605 +        public byte[] getCode() {
270.2606 +            return code;
270.2607 +        }
270.2608 +
270.2609 +        /**
270.2610 +         * Return LineNumberTable size.
270.2611 +         */
270.2612 +        public int getnumlines() {
270.2613 +            return lin_num_tb.size();
270.2614 +        }
270.2615 +
270.2616 +        /**
270.2617 +         * Return LineNumberTable
270.2618 +         */
270.2619 +        public Vector getlin_num_tb() {
270.2620 +            return lin_num_tb;
270.2621 +        }
270.2622 +
270.2623 +        /**
270.2624 +         * Return LocalVariableTable size.
270.2625 +         */
270.2626 +        public int getloc_var_tbsize() {
270.2627 +            return loc_var_tb.size();
270.2628 +        }
270.2629 +
270.2630 +        /**
270.2631 +         * Return LocalVariableTable.
270.2632 +         */
270.2633 +        public Vector getloc_var_tb() {
270.2634 +            return loc_var_tb;
270.2635 +        }
270.2636 +
270.2637 +        /**
270.2638 +         * Return StackMap.
270.2639 +         */
270.2640 +        public StackMapData[] getStackMap() {
270.2641 +            return stackMap;
270.2642 +        }
270.2643 +
270.2644 +        /**
270.2645 +         * Return StackMapTable.
270.2646 +         */
270.2647 +        public StackMapTableData[] getStackMapTable() {
270.2648 +            return stackMapTable;
270.2649 +        }
270.2650 +
270.2651 +        public StackMapIterator createStackMapIterator() {
270.2652 +            return new StackMapIterator(this);
270.2653 +        }
270.2654 +
270.2655 +        /**
270.2656 +         * Return true if method is static
270.2657 +         */
270.2658 +        public boolean isStatic() {
270.2659 +            if ((access & ACC_STATIC) != 0) {
270.2660 +                return true;
270.2661 +            }
270.2662 +            return false;
270.2663 +        }
270.2664 +
270.2665 +        /**
270.2666 +         * Return max depth of operand stack.
270.2667 +         */
270.2668 +        public int getMaxStack() {
270.2669 +            return max_stack;
270.2670 +        }
270.2671 +
270.2672 +        /**
270.2673 +         * Return number of local variables.
270.2674 +         */
270.2675 +        public int getMaxLocals() {
270.2676 +            return max_locals;
270.2677 +        }
270.2678 +
270.2679 +        /**
270.2680 +         * Return exception index table in Exception attribute.
270.2681 +         */
270.2682 +        public int[] get_exc_index_table() {
270.2683 +            return exc_index_table;
270.2684 +        }
270.2685 +
270.2686 +        /**
270.2687 +         * Return exception table in code attributre.
270.2688 +         */
270.2689 +        public TrapDataIterator getTrapDataIterator() {
270.2690 +            return new TrapDataIterator(exception_table);
270.2691 +        }
270.2692 +
270.2693 +        /**
270.2694 +         * Return method attributes.
270.2695 +         */
270.2696 +        public Vector getAttributes() {
270.2697 +            return attrs;
270.2698 +        }
270.2699 +
270.2700 +        /**
270.2701 +         * Return code attributes.
270.2702 +         */
270.2703 +        public Vector getCodeAttributes() {
270.2704 +            return code_attrs;
270.2705 +        }
270.2706 +
270.2707 +        /**
270.2708 +         * Return true if method id synthetic.
270.2709 +         */
270.2710 +        public boolean isSynthetic() {
270.2711 +            return isSynthetic;
270.2712 +        }
270.2713 +
270.2714 +        /**
270.2715 +         * Return true if method is deprecated.
270.2716 +         */
270.2717 +        public boolean isDeprecated() {
270.2718 +            return isDeprecated;
270.2719 +        }
270.2720 +
270.2721 +        public byte[] findAnnotationData(boolean classRetention) {
270.2722 +            String n = classRetention
270.2723 +                ? "RuntimeInvisibleAnnotations" : // NOI18N
270.2724 +                "RuntimeVisibleAnnotations"; // NOI18N
270.2725 +            AttrData[] arr = new AttrData[attrs.size()];
270.2726 +            attrs.copyInto(arr);
270.2727 +            return ClassData.findAttr(n, arr);
270.2728 +        }
270.2729 +
270.2730 +        public boolean isConstructor() {
270.2731 +            return "<init>".equals(getName());
270.2732 +        }
270.2733 +    }
270.2734 +
270.2735 +    /* represents one entry of StackMap attribute
270.2736 +     */
270.2737 +    private static class StackMapData {
270.2738 +
270.2739 +        final int offset;
270.2740 +        final int[] locals;
270.2741 +        final int[] stack;
270.2742 +
270.2743 +        StackMapData(int offset, int[] locals, int[] stack) {
270.2744 +            this.offset = offset;
270.2745 +            this.locals = locals;
270.2746 +            this.stack = stack;
270.2747 +        }
270.2748 +
270.2749 +        StackMapData(DataInputStream in, MethodData method) throws IOException {
270.2750 +            offset = in.readUnsignedShort();
270.2751 +            int local_size = in.readUnsignedShort();
270.2752 +            locals = readTypeArray(in, local_size, method);
270.2753 +            int stack_size = in.readUnsignedShort();
270.2754 +            stack = readTypeArray(in, stack_size, method);
270.2755 +        }
270.2756 +
270.2757 +        static final int[] readTypeArray(DataInputStream in, int length, MethodData method) throws IOException {
270.2758 +            int[] types = new int[length];
270.2759 +            for (int i = 0; i < length; i++) {
270.2760 +                types[i] = readType(in, method);
270.2761 +            }
270.2762 +            return types;
270.2763 +        }
270.2764 +
270.2765 +        static final int readType(DataInputStream in, MethodData method) throws IOException {
270.2766 +            int type = in.readUnsignedByte();
270.2767 +            if (type == ITEM_Object || type == ITEM_NewObject) {
270.2768 +                type = type | (in.readUnsignedShort() << 8);
270.2769 +            }
270.2770 +            return type;
270.2771 +        }
270.2772 +    }
270.2773 +
270.2774 +    static final class StackMapIterator {
270.2775 +
270.2776 +        private final StackMapTableData[] stackMapTable;
270.2777 +        private final TypeArray argTypes;
270.2778 +        private final TypeArray localTypes;
270.2779 +        private final TypeArray stackTypes;
270.2780 +        private int nextFrameIndex;
270.2781 +        private int lastFrameByteCodeOffset;
270.2782 +        private int byteCodeOffset;
270.2783 +
270.2784 +        StackMapIterator(final MethodData methodData) {
270.2785 +            this(methodData.getStackMapTable(),
270.2786 +                methodData.getInternalSig(),
270.2787 +                methodData.isStatic());
270.2788 +        }
270.2789 +
270.2790 +        StackMapIterator(final StackMapTableData[] stackMapTable,
270.2791 +            final String methodSignature,
270.2792 +            final boolean isStaticMethod) {
270.2793 +            this.stackMapTable = (stackMapTable != null)
270.2794 +                ? stackMapTable
270.2795 +                : new StackMapTableData[0];
270.2796 +
270.2797 +            argTypes = getArgTypes(methodSignature, isStaticMethod);
270.2798 +            localTypes = new TypeArray();
270.2799 +            stackTypes = new TypeArray();
270.2800 +
270.2801 +            localTypes.addAll(argTypes);
270.2802 +
270.2803 +            lastFrameByteCodeOffset = -1;
270.2804 +            advanceBy(0);
270.2805 +        }
270.2806 +
270.2807 +        public String getFrameAsString() {
270.2808 +            return (nextFrameIndex == 0)
270.2809 +                ? StackMapTableData.toString("INITIAL", 0, null, null)
270.2810 +                : stackMapTable[nextFrameIndex - 1].toString();
270.2811 +        }
270.2812 +
270.2813 +        public int getFrameIndex() {
270.2814 +            return nextFrameIndex;
270.2815 +        }
270.2816 +
270.2817 +        public TypeArray getFrameStack() {
270.2818 +            return stackTypes;
270.2819 +        }
270.2820 +
270.2821 +        public TypeArray getFrameLocals() {
270.2822 +            return localTypes;
270.2823 +        }
270.2824 +
270.2825 +        public TypeArray getArguments() {
270.2826 +            return argTypes;
270.2827 +        }
270.2828 +
270.2829 +        public void advanceBy(final int numByteCodes) {
270.2830 +            if (numByteCodes < 0) {
270.2831 +                throw new IllegalStateException("Forward only iterator");
270.2832 +            }
270.2833 +
270.2834 +            byteCodeOffset += numByteCodes;
270.2835 +            while ((nextFrameIndex < stackMapTable.length)
270.2836 +                && ((byteCodeOffset - lastFrameByteCodeOffset)
270.2837 +                >= (stackMapTable[nextFrameIndex].offsetDelta
270.2838 +                + 1))) {
270.2839 +                final StackMapTableData nextFrame = stackMapTable[nextFrameIndex];
270.2840 +
270.2841 +                lastFrameByteCodeOffset += nextFrame.offsetDelta + 1;
270.2842 +                nextFrame.applyTo(localTypes, stackTypes);
270.2843 +
270.2844 +                ++nextFrameIndex;
270.2845 +            }
270.2846 +        }
270.2847 +
270.2848 +        public void advanceTo(final int nextByteCodeOffset) {
270.2849 +            advanceBy(nextByteCodeOffset - byteCodeOffset);
270.2850 +        }
270.2851 +
270.2852 +        private static TypeArray getArgTypes(final String methodSignature,
270.2853 +            final boolean isStaticMethod) {
270.2854 +            final TypeArray argTypes = new TypeArray();
270.2855 +
270.2856 +            if (!isStaticMethod) {
270.2857 +                argTypes.add(ITEM_Object);
270.2858 +            }
270.2859 +
270.2860 +            if (methodSignature.charAt(0) != '(') {
270.2861 +                throw new IllegalArgumentException("Invalid method signature");
270.2862 +            }
270.2863 +
270.2864 +            final int length = methodSignature.length();
270.2865 +            boolean skipType = false;
270.2866 +            int argType;
270.2867 +            for (int i = 1; i < length; ++i) {
270.2868 +                switch (methodSignature.charAt(i)) {
270.2869 +                    case 'B':
270.2870 +                    case 'C':
270.2871 +                    case 'S':
270.2872 +                    case 'Z':
270.2873 +                    case 'I':
270.2874 +                        argType = ITEM_Integer;
270.2875 +                        break;
270.2876 +                    case 'J':
270.2877 +                        argType = ITEM_Long;
270.2878 +                        break;
270.2879 +                    case 'F':
270.2880 +                        argType = ITEM_Float;
270.2881 +                        break;
270.2882 +                    case 'D':
270.2883 +                        argType = ITEM_Double;
270.2884 +                        break;
270.2885 +                    case 'L': {
270.2886 +                        i = methodSignature.indexOf(';', i + 1);
270.2887 +                        if (i == -1) {
270.2888 +                            throw new IllegalArgumentException(
270.2889 +                                "Invalid method signature");
270.2890 +                        }
270.2891 +                        argType = ITEM_Object;
270.2892 +                        break;
270.2893 +                    }
270.2894 +                    case ')':
270.2895 +                        // not interested in the return value type
270.2896 +                        return argTypes;
270.2897 +                    case '[':
270.2898 +                        if (!skipType) {
270.2899 +                            argTypes.add(ITEM_Object);
270.2900 +                            skipType = true;
270.2901 +                        }
270.2902 +                        continue;
270.2903 +
270.2904 +                    default:
270.2905 +                        throw new IllegalArgumentException(
270.2906 +                            "Invalid method signature");
270.2907 +                }
270.2908 +
270.2909 +                if (!skipType) {
270.2910 +                    argTypes.add(argType);
270.2911 +                } else {
270.2912 +                    skipType = false;
270.2913 +                }
270.2914 +            }
270.2915 +
270.2916 +            return argTypes;
270.2917 +        }
270.2918 +    }
270.2919 +    /* represents one entry of StackMapTable attribute
270.2920 +     */
270.2921 +
270.2922 +    private static abstract class StackMapTableData {
270.2923 +
270.2924 +        final int frameType;
270.2925 +        int offsetDelta;
270.2926 +
270.2927 +        StackMapTableData(int frameType) {
270.2928 +            this.frameType = frameType;
270.2929 +        }
270.2930 +
270.2931 +        abstract void applyTo(TypeArray localTypes, TypeArray stackTypes);
270.2932 +
270.2933 +        protected static String toString(
270.2934 +            final String frameType,
270.2935 +            final int offset,
270.2936 +            final int[] localTypes,
270.2937 +            final int[] stackTypes) {
270.2938 +            final StringBuilder sb = new StringBuilder(frameType);
270.2939 +
270.2940 +            sb.append("(off: +").append(offset);
270.2941 +            if (localTypes != null) {
270.2942 +                sb.append(", locals: ");
270.2943 +                appendTypes(sb, localTypes);
270.2944 +            }
270.2945 +            if (stackTypes != null) {
270.2946 +                sb.append(", stack: ");
270.2947 +                appendTypes(sb, stackTypes);
270.2948 +            }
270.2949 +            sb.append(')');
270.2950 +
270.2951 +            return sb.toString();
270.2952 +        }
270.2953 +
270.2954 +        private static void appendTypes(final StringBuilder sb, final int[] types) {
270.2955 +            sb.append('[');
270.2956 +            if (types.length > 0) {
270.2957 +                sb.append(TypeArray.typeString(types[0]));
270.2958 +                for (int i = 1; i < types.length; ++i) {
270.2959 +                    sb.append(", ");
270.2960 +                    sb.append(TypeArray.typeString(types[i]));
270.2961 +                }
270.2962 +            }
270.2963 +            sb.append(']');
270.2964 +        }
270.2965 +
270.2966 +        private static class SameFrame extends StackMapTableData {
270.2967 +
270.2968 +            SameFrame(int frameType, int offsetDelta) {
270.2969 +                super(frameType);
270.2970 +                this.offsetDelta = offsetDelta;
270.2971 +            }
270.2972 +
270.2973 +            @Override
270.2974 +            void applyTo(TypeArray localTypes, TypeArray stackTypes) {
270.2975 +                stackTypes.clear();
270.2976 +            }
270.2977 +
270.2978 +            @Override
270.2979 +            public String toString() {
270.2980 +                return toString("SAME" + ((frameType == SAME_FRAME_EXTENDED)
270.2981 +                    ? "_FRAME_EXTENDED" : ""),
270.2982 +                    offsetDelta,
270.2983 +                    null, null);
270.2984 +            }
270.2985 +        }
270.2986 +
270.2987 +        private static class SameLocals1StackItem extends StackMapTableData {
270.2988 +
270.2989 +            final int[] stack;
270.2990 +
270.2991 +            SameLocals1StackItem(int frameType, int offsetDelta, int[] stack) {
270.2992 +                super(frameType);
270.2993 +                this.offsetDelta = offsetDelta;
270.2994 +                this.stack = stack;
270.2995 +            }
270.2996 +
270.2997 +            @Override
270.2998 +            void applyTo(TypeArray localTypes, TypeArray stackTypes) {
270.2999 +                stackTypes.setAll(stack);
270.3000 +            }
270.3001 +
270.3002 +            @Override
270.3003 +            public String toString() {
270.3004 +                return toString(
270.3005 +                    "SAME_LOCALS_1_STACK_ITEM"
270.3006 +                    + ((frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED)
270.3007 +                    ? "_EXTENDED" : ""),
270.3008 +                    offsetDelta,
270.3009 +                    null, stack);
270.3010 +            }
270.3011 +        }
270.3012 +
270.3013 +        private static class ChopFrame extends StackMapTableData {
270.3014 +
270.3015 +            ChopFrame(int frameType, int offsetDelta) {
270.3016 +                super(frameType);
270.3017 +                this.offsetDelta = offsetDelta;
270.3018 +            }
270.3019 +
270.3020 +            @Override
270.3021 +            void applyTo(TypeArray localTypes, TypeArray stackTypes) {
270.3022 +                localTypes.setSize(localTypes.getSize()
270.3023 +                    - (SAME_FRAME_EXTENDED - frameType));
270.3024 +                stackTypes.clear();
270.3025 +            }
270.3026 +
270.3027 +            @Override
270.3028 +            public String toString() {
270.3029 +                return toString("CHOP", offsetDelta, null, null);
270.3030 +            }
270.3031 +        }
270.3032 +
270.3033 +        private static class AppendFrame extends StackMapTableData {
270.3034 +
270.3035 +            final int[] locals;
270.3036 +
270.3037 +            AppendFrame(int frameType, int offsetDelta, int[] locals) {
270.3038 +                super(frameType);
270.3039 +                this.offsetDelta = offsetDelta;
270.3040 +                this.locals = locals;
270.3041 +            }
270.3042 +
270.3043 +            @Override
270.3044 +            void applyTo(TypeArray localTypes, TypeArray stackTypes) {
270.3045 +                localTypes.addAll(locals);
270.3046 +                stackTypes.clear();
270.3047 +            }
270.3048 +
270.3049 +            @Override
270.3050 +            public String toString() {
270.3051 +                return toString("APPEND", offsetDelta, locals, null);
270.3052 +            }
270.3053 +        }
270.3054 +
270.3055 +        private static class FullFrame extends StackMapTableData {
270.3056 +
270.3057 +            final int[] locals;
270.3058 +            final int[] stack;
270.3059 +
270.3060 +            FullFrame(int offsetDelta, int[] locals, int[] stack) {
270.3061 +                super(FULL_FRAME);
270.3062 +                this.offsetDelta = offsetDelta;
270.3063 +                this.locals = locals;
270.3064 +                this.stack = stack;
270.3065 +            }
270.3066 +
270.3067 +            @Override
270.3068 +            void applyTo(TypeArray localTypes, TypeArray stackTypes) {
270.3069 +                localTypes.setAll(locals);
270.3070 +                stackTypes.setAll(stack);
270.3071 +            }
270.3072 +
270.3073 +            @Override
270.3074 +            public String toString() {
270.3075 +                return toString("FULL", offsetDelta, locals, stack);
270.3076 +            }
270.3077 +        }
270.3078 +
270.3079 +        static StackMapTableData getInstance(DataInputStream in, MethodData method)
270.3080 +            throws IOException {
270.3081 +            int frameType = in.readUnsignedByte();
270.3082 +
270.3083 +            if (frameType < SAME_FRAME_BOUND) {
270.3084 +                // same_frame
270.3085 +                return new SameFrame(frameType, frameType);
270.3086 +            } else if (SAME_FRAME_BOUND <= frameType && frameType < SAME_LOCALS_1_STACK_ITEM_BOUND) {
270.3087 +                // same_locals_1_stack_item_frame
270.3088 +                // read additional single stack element
270.3089 +                return new SameLocals1StackItem(frameType,
270.3090 +                    (frameType - SAME_FRAME_BOUND),
270.3091 +                    StackMapData.readTypeArray(in, 1, method));
270.3092 +            } else if (frameType == SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
270.3093 +                // same_locals_1_stack_item_extended
270.3094 +                return new SameLocals1StackItem(frameType,
270.3095 +                    in.readUnsignedShort(),
270.3096 +                    StackMapData.readTypeArray(in, 1, method));
270.3097 +            } else if (SAME_LOCALS_1_STACK_ITEM_EXTENDED < frameType && frameType < SAME_FRAME_EXTENDED) {
270.3098 +                // chop_frame or same_frame_extended
270.3099 +                return new ChopFrame(frameType, in.readUnsignedShort());
270.3100 +            } else if (frameType == SAME_FRAME_EXTENDED) {
270.3101 +                // chop_frame or same_frame_extended
270.3102 +                return new SameFrame(frameType, in.readUnsignedShort());
270.3103 +            } else if (SAME_FRAME_EXTENDED < frameType && frameType < FULL_FRAME) {
270.3104 +                // append_frame
270.3105 +                return new AppendFrame(frameType, in.readUnsignedShort(),
270.3106 +                    StackMapData.readTypeArray(in, frameType - SAME_FRAME_EXTENDED, method));
270.3107 +            } else if (frameType == FULL_FRAME) {
270.3108 +                // full_frame
270.3109 +                int offsetDelta = in.readUnsignedShort();
270.3110 +                int locals_size = in.readUnsignedShort();
270.3111 +                int[] locals = StackMapData.readTypeArray(in, locals_size, method);
270.3112 +                int stack_size = in.readUnsignedShort();
270.3113 +                int[] stack = StackMapData.readTypeArray(in, stack_size, method);
270.3114 +                return new FullFrame(offsetDelta, locals, stack);
270.3115 +            } else {
270.3116 +                throw new ClassFormatError("unrecognized frame_type in StackMapTable");
270.3117 +            }
270.3118 +        }
270.3119 +    }
270.3120 +
270.3121 +    /**
270.3122 +     * Stores exception table data in code attribute.
270.3123 +     *
270.3124 +     * @author Sucheta Dambalkar (Adopted code from jdis)
270.3125 +     */
270.3126 +    static final class TrapData {
270.3127 +
270.3128 +        public final short start_pc;
270.3129 +        public final short end_pc;
270.3130 +        public final short handler_pc;
270.3131 +        public final short catch_cpx;
270.3132 +        final int num;
270.3133 +
270.3134 +        /**
270.3135 +         * Read and store exception table data in code attribute.
270.3136 +         */
270.3137 +        TrapData(DataInputStream in, int num) throws IOException {
270.3138 +            this.num = num;
270.3139 +            start_pc = in.readShort();
270.3140 +            end_pc = in.readShort();
270.3141 +            handler_pc = in.readShort();
270.3142 +            catch_cpx = in.readShort();
270.3143 +        }
270.3144 +
270.3145 +        /**
270.3146 +         * returns recommended identifier
270.3147 +         */
270.3148 +        public String ident() {
270.3149 +            return "t" + num;
270.3150 +        }
270.3151 +    }
270.3152 +    /**
270.3153 +     *
270.3154 +     * @author Jaroslav Tulach <jtulach@netbeans.org>
270.3155 +     */
270.3156 +    static final class TrapDataIterator {
270.3157 +
270.3158 +        private final Hashtable exStart = new Hashtable();
270.3159 +        private final Hashtable exStop = new Hashtable();
270.3160 +        private TrapData[] current = new TrapData[10];
270.3161 +        private int currentCount;
270.3162 +
270.3163 +        TrapDataIterator(Vector exceptionTable) {
270.3164 +            for (int i = 0; i < exceptionTable.size(); i++) {
270.3165 +                final TrapData td = (TrapData) exceptionTable.elementAt(i);
270.3166 +                put(exStart, td.start_pc, td);
270.3167 +                put(exStop, td.end_pc, td);
270.3168 +            }
270.3169 +        }
270.3170 +
270.3171 +        private static void put(Hashtable h, short key, TrapData td) {
270.3172 +            Short s = Short.valueOf((short) key);
270.3173 +            Vector v = (Vector) h.get(s);
270.3174 +            if (v == null) {
270.3175 +                v = new Vector(1);
270.3176 +                h.put(s, v);
270.3177 +            }
270.3178 +            v.add(td);
270.3179 +        }
270.3180 +
270.3181 +        private boolean processAll(Hashtable h, Short key, boolean add) {
270.3182 +            boolean change = false;
270.3183 +            Vector v = (Vector) h.get(key);
270.3184 +            if (v != null) {
270.3185 +                int s = v.size();
270.3186 +                for (int i = 0; i < s; i++) {
270.3187 +                    TrapData td = (TrapData) v.elementAt(i);
270.3188 +                    if (add) {
270.3189 +                        add(td);
270.3190 +                        change = true;
270.3191 +                    } else {
270.3192 +                        remove(td);
270.3193 +                        change = true;
270.3194 +                    }
270.3195 +                }
270.3196 +            }
270.3197 +            return change;
270.3198 +        }
270.3199 +
270.3200 +        public boolean advanceTo(int i) {
270.3201 +            Short s = Short.valueOf((short) i);
270.3202 +            boolean ch1 = processAll(exStart, s, true);
270.3203 +            boolean ch2 = processAll(exStop, s, false);
270.3204 +            return ch1 || ch2;
270.3205 +        }
270.3206 +
270.3207 +        public boolean useTry() {
270.3208 +            return currentCount > 0;
270.3209 +        }
270.3210 +
270.3211 +        public TrapData[] current() {
270.3212 +            TrapData[] copy = new TrapData[currentCount];
270.3213 +            for (int i = 0; i < currentCount; i++) {
270.3214 +                copy[i] = current[i];
270.3215 +            }
270.3216 +            return copy;
270.3217 +        }
270.3218 +
270.3219 +        private void add(TrapData e) {
270.3220 +            if (currentCount == current.length) {
270.3221 +                TrapData[] data = new TrapData[currentCount * 2];
270.3222 +                for (int i = 0; i < currentCount; i++) {
270.3223 +                    data[i] = current[i];
270.3224 +                }
270.3225 +                current = data;
270.3226 +            }
270.3227 +            current[currentCount++] = e;
270.3228 +        }
270.3229 +
270.3230 +        private void remove(TrapData e) {
270.3231 +            if (currentCount == 0) {
270.3232 +                return;
270.3233 +            }
270.3234 +            int from = 0;
270.3235 +            while (from < currentCount) {
270.3236 +                if (e == current[from++]) {
270.3237 +                    break;
270.3238 +                }
270.3239 +            }
270.3240 +            while (from < currentCount) {
270.3241 +                current[from - 1] = current[from];
270.3242 +                current[from] = null;
270.3243 +                from++;
270.3244 +            }
270.3245 +            currentCount--;
270.3246 +        }
270.3247 +    }
270.3248 +    static final class TypeArray {
270.3249 +
270.3250 +        private static final int CAPACITY_INCREMENT = 16;
270.3251 +        private int[] types;
270.3252 +        private int size;
270.3253 +
270.3254 +        public TypeArray() {
270.3255 +        }
270.3256 +
270.3257 +        public TypeArray(final TypeArray initialTypes) {
270.3258 +            setAll(initialTypes);
270.3259 +        }
270.3260 +
270.3261 +        public void add(final int newType) {
270.3262 +            ensureCapacity(size + 1);
270.3263 +            types[size++] = newType;
270.3264 +        }
270.3265 +
270.3266 +        public void addAll(final TypeArray newTypes) {
270.3267 +            addAll(newTypes.types, 0, newTypes.size);
270.3268 +        }
270.3269 +
270.3270 +        public void addAll(final int[] newTypes) {
270.3271 +            addAll(newTypes, 0, newTypes.length);
270.3272 +        }
270.3273 +
270.3274 +        public void addAll(final int[] newTypes,
270.3275 +            final int offset,
270.3276 +            final int count) {
270.3277 +            if (count > 0) {
270.3278 +                ensureCapacity(size + count);
270.3279 +                arraycopy(newTypes, offset, types, size, count);
270.3280 +                size += count;
270.3281 +            }
270.3282 +        }
270.3283 +
270.3284 +        public void set(final int index, final int newType) {
270.3285 +            types[index] = newType;
270.3286 +        }
270.3287 +
270.3288 +        public void setAll(final TypeArray newTypes) {
270.3289 +            setAll(newTypes.types, 0, newTypes.size);
270.3290 +        }
270.3291 +
270.3292 +        public void setAll(final int[] newTypes) {
270.3293 +            setAll(newTypes, 0, newTypes.length);
270.3294 +        }
270.3295 +
270.3296 +        public void setAll(final int[] newTypes,
270.3297 +            final int offset,
270.3298 +            final int count) {
270.3299 +            if (count > 0) {
270.3300 +                ensureCapacity(count);
270.3301 +                arraycopy(newTypes, offset, types, 0, count);
270.3302 +                size = count;
270.3303 +            } else {
270.3304 +                clear();
270.3305 +            }
270.3306 +        }
270.3307 +
270.3308 +        public void setSize(final int newSize) {
270.3309 +            if (size != newSize) {
270.3310 +                ensureCapacity(newSize);
270.3311 +
270.3312 +                for (int i = size; i < newSize; ++i) {
270.3313 +                    types[i] = 0;
270.3314 +                }
270.3315 +                size = newSize;
270.3316 +            }
270.3317 +        }
270.3318 +
270.3319 +        public void clear() {
270.3320 +            size = 0;
270.3321 +        }
270.3322 +
270.3323 +        public int getSize() {
270.3324 +            return size;
270.3325 +        }
270.3326 +
270.3327 +        public int get(final int index) {
270.3328 +            return types[index];
270.3329 +        }
270.3330 +
270.3331 +        public static String typeString(final int type) {
270.3332 +            switch (type & 0xff) {
270.3333 +                case ITEM_Bogus:
270.3334 +                    return "_top_";
270.3335 +                case ITEM_Integer:
270.3336 +                    return "_int_";
270.3337 +                case ITEM_Float:
270.3338 +                    return "_float_";
270.3339 +                case ITEM_Double:
270.3340 +                    return "_double_";
270.3341 +                case ITEM_Long:
270.3342 +                    return "_long_";
270.3343 +                case ITEM_Null:
270.3344 +                    return "_null_";
270.3345 +                case ITEM_InitObject: // UninitializedThis
270.3346 +                    return "_init_";
270.3347 +                case ITEM_Object:
270.3348 +                    return "_object_";
270.3349 +                case ITEM_NewObject: // Uninitialized
270.3350 +                    return "_new_";
270.3351 +                default:
270.3352 +                    throw new IllegalArgumentException("Unknown type");
270.3353 +            }
270.3354 +        }
270.3355 +
270.3356 +        @Override
270.3357 +        public String toString() {
270.3358 +            final StringBuilder sb = new StringBuilder("[");
270.3359 +            if (size > 0) {
270.3360 +                sb.append(typeString(types[0]));
270.3361 +                for (int i = 1; i < size; ++i) {
270.3362 +                    sb.append(", ");
270.3363 +                    sb.append(typeString(types[i]));
270.3364 +                }
270.3365 +            }
270.3366 +
270.3367 +            return sb.append(']').toString();
270.3368 +        }
270.3369 +
270.3370 +        private void ensureCapacity(final int minCapacity) {
270.3371 +            if ((minCapacity == 0)
270.3372 +                || (types != null) && (minCapacity <= types.length)) {
270.3373 +                return;
270.3374 +            }
270.3375 +
270.3376 +            final int newCapacity =
270.3377 +                ((minCapacity + CAPACITY_INCREMENT - 1) / CAPACITY_INCREMENT)
270.3378 +                * CAPACITY_INCREMENT;
270.3379 +            final int[] newTypes = new int[newCapacity];
270.3380 +
270.3381 +            if (size > 0) {
270.3382 +                arraycopy(types, 0, newTypes, 0, size);
270.3383 +            }
270.3384 +
270.3385 +            types = newTypes;
270.3386 +        }
270.3387 +
270.3388 +        // no System.arraycopy
270.3389 +        private void arraycopy(final int[] src, final int srcPos,
270.3390 +            final int[] dest, final int destPos,
270.3391 +            final int length) {
270.3392 +            for (int i = 0; i < length; ++i) {
270.3393 +                dest[destPos + i] = src[srcPos + i];
270.3394 +            }
270.3395 +        }
270.3396 +    }
270.3397 +    /**
270.3398 +     * A JavaScript ready replacement for java.util.Vector
270.3399 +     *
270.3400 +     * @author Jaroslav Tulach <jtulach@netbeans.org>
270.3401 +     */
270.3402 +    @JavaScriptPrototype(prototype = "new Array")
270.3403 +    private static final class Vector {
270.3404 +
270.3405 +        private Object[] arr;
270.3406 +
270.3407 +        Vector() {
270.3408 +        }
270.3409 +
270.3410 +        Vector(int i) {
270.3411 +        }
270.3412 +
270.3413 +        void add(Object objectType) {
270.3414 +            addElement(objectType);
270.3415 +        }
270.3416 +
270.3417 +        @JavaScriptBody(args = {"obj"}, body =
270.3418 +            "this.push(obj);")
270.3419 +        void addElement(Object obj) {
270.3420 +            final int s = size();
270.3421 +            setSize(s + 1);
270.3422 +            setElementAt(obj, s);
270.3423 +        }
270.3424 +
270.3425 +        @JavaScriptBody(args = {}, body =
270.3426 +            "return this.length;")
270.3427 +        int size() {
270.3428 +            return arr == null ? 0 : arr.length;
270.3429 +        }
270.3430 +
270.3431 +        @JavaScriptBody(args = {"newArr"}, body =
270.3432 +            "for (var i = 0; i < this.length; i++) {\n"
270.3433 +            + "  newArr[i] = this[i];\n"
270.3434 +            + "}\n")
270.3435 +        void copyInto(Object[] newArr) {
270.3436 +            if (arr == null) {
270.3437 +                return;
270.3438 +            }
270.3439 +            int min = Math.min(newArr.length, arr.length);
270.3440 +            for (int i = 0; i < min; i++) {
270.3441 +                newArr[i] = arr[i];
270.3442 +            }
270.3443 +        }
270.3444 +
270.3445 +        @JavaScriptBody(args = {"index"}, body =
270.3446 +            "return this[index];")
270.3447 +        Object elementAt(int index) {
270.3448 +            return arr[index];
270.3449 +        }
270.3450 +
270.3451 +        private void setSize(int len) {
270.3452 +            Object[] newArr = new Object[len];
270.3453 +            copyInto(newArr);
270.3454 +            arr = newArr;
270.3455 +        }
270.3456 +
270.3457 +        @JavaScriptBody(args = {"val", "index"}, body =
270.3458 +            "this[index] = val;")
270.3459 +        void setElementAt(Object val, int index) {
270.3460 +            arr[index] = val;
270.3461 +        }
270.3462 +    }
270.3463 +    
270.3464 +}
   271.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Wed Feb 27 17:50:47 2013 +0100
   271.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ByteCodeToJavaScript.java	Mon Oct 07 14:20:58 2013 +0200
   271.3 @@ -19,15 +19,7 @@
   271.4  
   271.5  import java.io.IOException;
   271.6  import java.io.InputStream;
   271.7 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
   271.8 -import org.apidesign.javap.AnnotationParser;
   271.9 -import org.apidesign.javap.ClassData;
  271.10 -import org.apidesign.javap.FieldData;
  271.11 -import org.apidesign.javap.MethodData;
  271.12 -import org.apidesign.javap.StackMapIterator;
  271.13 -import static org.apidesign.javap.RuntimeConstants.*;
  271.14 -import org.apidesign.javap.TrapData;
  271.15 -import org.apidesign.javap.TrapDataIterator;
  271.16 +import static org.apidesign.vm4brwsr.ByteCodeParser.*;
  271.17  
  271.18  /** Translator of the code inside class files to JavaScript.
  271.19   *
  271.20 @@ -36,9 +28,16 @@
  271.21  abstract class ByteCodeToJavaScript {
  271.22      private ClassData jc;
  271.23      final Appendable out;
  271.24 +    final ObfuscationDelegate obfuscationDelegate;
  271.25  
  271.26      protected ByteCodeToJavaScript(Appendable out) {
  271.27 +        this(out, ObfuscationDelegate.NULL);
  271.28 +    }
  271.29 +
  271.30 +    protected ByteCodeToJavaScript(
  271.31 +            Appendable out, ObfuscationDelegate obfuscationDelegate) {
  271.32          this.out = out;
  271.33 +        this.obfuscationDelegate = obfuscationDelegate;
  271.34      }
  271.35      
  271.36      /* Collects additional required resources.
  271.37 @@ -66,7 +65,9 @@
  271.38      /* protected */ String accessClass(String classOperation) {
  271.39          return classOperation;
  271.40      }
  271.41 -    
  271.42 +
  271.43 +    abstract String getVMObject();
  271.44 +
  271.45      /** Prints out a debug message. 
  271.46       * 
  271.47       * @param msg the message
  271.48 @@ -95,14 +96,34 @@
  271.49              );
  271.50          }
  271.51          byte[] arrData = jc.findAnnotationData(true);
  271.52 -        String[] arr = findAnnotation(arrData, jc, 
  271.53 -            "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
  271.54 -            "resource", "processByteCode"
  271.55 -        );
  271.56 -        if (arr != null) {
  271.57 -            requireScript(arr[0]);
  271.58 -            if ("0".equals(arr[1])) {
  271.59 -                return null;
  271.60 +        {
  271.61 +            String[] arr = findAnnotation(arrData, jc, 
  271.62 +                "org.apidesign.bck2brwsr.core.ExtraJavaScript", 
  271.63 +                "resource", "processByteCode"
  271.64 +            );
  271.65 +            if (arr != null) {
  271.66 +                if (!arr[0].isEmpty()) {
  271.67 +                    requireScript(arr[0]);
  271.68 +                }
  271.69 +                if ("0".equals(arr[1])) {
  271.70 +                    return null;
  271.71 +                }
  271.72 +            }
  271.73 +        }
  271.74 +        {
  271.75 +            String[] arr = findAnnotation(arrData, jc, 
  271.76 +                "net.java.html.js.JavaScriptResource", 
  271.77 +                "value"
  271.78 +            );
  271.79 +            if (arr != null) {
  271.80 +                if (arr[0].startsWith("/")) {
  271.81 +                    requireScript(arr[0]);
  271.82 +                } else {
  271.83 +                    int last = jc.getClassName().lastIndexOf('/');
  271.84 +                    requireScript(
  271.85 +                        jc.getClassName().substring(0, last + 1).replace('.', '/') + arr[0]
  271.86 +                    );
  271.87 +                }
  271.88              }
  271.89          }
  271.90          String[] proto = findAnnotation(arrData, jc, 
  271.91 @@ -112,7 +133,8 @@
  271.92          StringArray toInitilize = new StringArray();
  271.93          final String className = className(jc);
  271.94          out.append("\n\n").append(assignClass(className));
  271.95 -        out.append("function CLS() {");
  271.96 +        out.append("function ").append(className).append("() {");
  271.97 +        out.append("\n  var CLS = ").append(className).append(';');
  271.98          out.append("\n  if (!CLS.$class) {");
  271.99          if (proto == null) {
 271.100              String sc = jc.getSuperClassName(); // with _
 271.101 @@ -132,6 +154,10 @@
 271.102          for (FieldData v : jc.getFields()) {
 271.103              if (v.isStatic()) {
 271.104                  out.append("\n  CLS.").append(v.getName()).append(initField(v));
 271.105 +                out.append("\n  c._").append(v.getName()).append(" = function (v) {")
 271.106 +                   .append("  if (arguments.length == 1) CLS.").append(v.getName())
 271.107 +                   .append(" = v; return CLS.").
 271.108 +                    append(v.getName()).append("; };");
 271.109              } else {
 271.110                  out.append("\n  c._").append(v.getName()).append(" = function (v) {")
 271.111                     .append("  if (arguments.length == 1) this.fld_").
 271.112 @@ -140,6 +166,8 @@
 271.113                      append(className).append('_').append(v.getName())
 271.114                     .append("; };");
 271.115              }
 271.116 +
 271.117 +            obfuscationDelegate.exportField(out, "c", "_" + v.getName(), v);
 271.118          }
 271.119          for (MethodData m : jc.getMethods()) {
 271.120              byte[] onlyArr = m.findAnnotationData(true);
 271.121 @@ -154,34 +182,44 @@
 271.122                  }
 271.123                  continue;
 271.124              }
 271.125 -            String prefix;
 271.126 +            String destObject;
 271.127              String mn;
 271.128 +            out.append("\n    ");
 271.129              if (m.isStatic()) {
 271.130 -                prefix = "\n    c.";
 271.131 -                mn = generateStaticMethod(prefix, m, toInitilize);
 271.132 +                destObject = "c";
 271.133 +                mn = generateStaticMethod(destObject, m, toInitilize);
 271.134              } else {
 271.135                  if (m.isConstructor()) {
 271.136 -                    prefix = "\n    CLS.";
 271.137 -                    mn = generateInstanceMethod(prefix, m);
 271.138 +                    destObject = "CLS";
 271.139 +                    mn = generateInstanceMethod(destObject, m);
 271.140                  } else {
 271.141 -                    prefix = "\n    c.";
 271.142 -                    mn = generateInstanceMethod(prefix, m);
 271.143 +                    destObject = "c";
 271.144 +                    mn = generateInstanceMethod(destObject, m);
 271.145                  }
 271.146              }
 271.147 +            obfuscationDelegate.exportMethod(out, destObject, mn, m);
 271.148              byte[] runAnno = m.findAnnotationData(false);
 271.149              if (runAnno != null) {
 271.150 -                out.append(prefix).append(mn).append(".anno = {");
 271.151 +                out.append("\n    ").append(destObject).append(".").append(mn).append(".anno = {");
 271.152                  generateAnno(jc, out, runAnno);
 271.153                  out.append("\n    };");
 271.154              }
 271.155 -            out.append(prefix).append(mn).append(".access = " + m.getAccess()).append(";");
 271.156 -            out.append(prefix).append(mn).append(".cls = CLS;");
 271.157 +            out.append("\n    ").append(destObject).append(".").append(mn).append(".access = " + m.getAccess()).append(";");
 271.158 +            out.append("\n    ").append(destObject).append(".").append(mn).append(".cls = CLS;");
 271.159          }
 271.160          out.append("\n    c.constructor = CLS;");
 271.161 -        out.append("\n    c.$instOf_").append(className).append(" = true;");
 271.162 +        out.append("\n    function fillInstOf(x) {");
 271.163 +        String instOfName = "$instOf_" + className;
 271.164 +        out.append("\n        x.").append(instOfName).append(" = true;");
 271.165          for (String superInterface : jc.getSuperInterfaces()) {
 271.166 -            out.append("\n    c.$instOf_").append(superInterface.replace('/', '_')).append(" = true;");
 271.167 +            String intrfc = superInterface.replace('/', '_');
 271.168 +            out.append("\n      vm.").append(intrfc).append("(false).fillInstOf(x);");
 271.169 +            requireReference(superInterface);
 271.170          }
 271.171 +        out.append("\n    }");
 271.172 +        out.append("\n    c.fillInstOf = fillInstOf;");
 271.173 +        out.append("\n    fillInstOf(c);");
 271.174 +        obfuscationDelegate.exportJSProperty(out, "c", instOfName);
 271.175          out.append("\n    CLS.$class = 'temp';");
 271.176          out.append("\n    CLS.$class = ");
 271.177          out.append(accessClass("java_lang_Class(true);"));
 271.178 @@ -195,6 +233,9 @@
 271.179              generateAnno(jc, out, classAnno);
 271.180              out.append("\n    };");
 271.181          }
 271.182 +        for (String init : toInitilize.toArray()) {
 271.183 +            out.append("\n    ").append(init).append("();");
 271.184 +        }
 271.185          out.append("\n  }");
 271.186          out.append("\n  if (arguments.length === 0) {");
 271.187          out.append("\n    if (!(this instanceof CLS)) {");
 271.188 @@ -223,14 +264,17 @@
 271.189          out.append("\n  }");
 271.190          out.append("\n  return arguments[0] ? new CLS() : CLS.prototype;");
 271.191          out.append("\n};");
 271.192 -        StringBuilder sb = new StringBuilder();
 271.193 -        for (String init : toInitilize.toArray()) {
 271.194 -            sb.append("\n").append(init).append("();");
 271.195 -        }
 271.196 -        return sb.toString();
 271.197 +
 271.198 +        obfuscationDelegate.exportClass(out, getVMObject(), className, jc);
 271.199 +
 271.200 +//        StringBuilder sb = new StringBuilder();
 271.201 +//        for (String init : toInitilize.toArray()) {
 271.202 +//            sb.append("\n").append(init).append("();");
 271.203 +//        }
 271.204 +        return "";
 271.205      }
 271.206 -    private String generateStaticMethod(String prefix, MethodData m, StringArray toInitilize) throws IOException {
 271.207 -        String jsb = javaScriptBody(prefix, m, true);
 271.208 +    private String generateStaticMethod(String destObject, MethodData m, StringArray toInitilize) throws IOException {
 271.209 +        String jsb = javaScriptBody(destObject, m, true);
 271.210          if (jsb != null) {
 271.211              return jsb;
 271.212          }
 271.213 @@ -238,28 +282,28 @@
 271.214          if (mn.equals("class__V")) {
 271.215              toInitilize.add(accessClass(className(jc)) + "(false)." + mn);
 271.216          }
 271.217 -        generateMethod(prefix, mn, m);
 271.218 +        generateMethod(destObject, mn, m);
 271.219          return mn;
 271.220      }
 271.221  
 271.222 -    private String generateInstanceMethod(String prefix, MethodData m) throws IOException {
 271.223 -        String jsb = javaScriptBody(prefix, m, false);
 271.224 +    private String generateInstanceMethod(String destObject, MethodData m) throws IOException {
 271.225 +        String jsb = javaScriptBody(destObject, m, false);
 271.226          if (jsb != null) {
 271.227              return jsb;
 271.228          }
 271.229          final String mn = findMethodName(m, new StringBuilder());
 271.230 -        generateMethod(prefix, mn, m);
 271.231 +        generateMethod(destObject, mn, m);
 271.232          return mn;
 271.233      }
 271.234  
 271.235 -    private void generateMethod(String prefix, String name, MethodData m)
 271.236 +    private void generateMethod(String destObject, String name, MethodData m)
 271.237              throws IOException {
 271.238          final StackMapIterator stackMapIterator = m.createStackMapIterator();
 271.239          TrapDataIterator trap = m.getTrapDataIterator();
 271.240          final LocalsMapper lmapper =
 271.241                  new LocalsMapper(stackMapIterator.getArguments());
 271.242  
 271.243 -        out.append(prefix).append(name).append(" = function(");
 271.244 +        out.append(destObject).append(".").append(name).append(" = function(");
 271.245          lmapper.outputArguments(out, m.isStatic());
 271.246          out.append(") {").append("\n");
 271.247  
 271.248 @@ -282,22 +326,36 @@
 271.249          TrapData[] previousTrap = null;
 271.250          boolean wide = false;
 271.251          
 271.252 -        out.append("\n  var gt = 0;\n  for(;;) switch(gt) {\n");
 271.253 +        out.append("\n  var gt = 0;\n");
 271.254 +        int openBraces = 0;
 271.255 +        int topMostLabel = 0;
 271.256          for (int i = 0; i < byteCodes.length; i++) {
 271.257              int prev = i;
 271.258              stackMapIterator.advanceTo(i);
 271.259              boolean changeInCatch = trap.advanceTo(i);
 271.260              if (changeInCatch || lastStackFrame != stackMapIterator.getFrameIndex()) {
 271.261                  if (previousTrap != null) {
 271.262 -                    generateCatch(previousTrap);
 271.263 +                    generateCatch(previousTrap, i, topMostLabel);
 271.264                      previousTrap = null;
 271.265                  }
 271.266              }
 271.267              if (lastStackFrame != stackMapIterator.getFrameIndex()) {
 271.268 +                if (i != 0) {
 271.269 +                    out.append("    }\n");
 271.270 +                }
 271.271 +                if (openBraces > 64) {
 271.272 +                    for (int c = 0; c < 64; c++) {
 271.273 +                        out.append("break;}\n");
 271.274 +                    }
 271.275 +                    openBraces = 1;
 271.276 +                    topMostLabel = i;
 271.277 +                }
 271.278 +                
 271.279                  lastStackFrame = stackMapIterator.getFrameIndex();
 271.280                  lmapper.syncWithFrameLocals(stackMapIterator.getFrameLocals());
 271.281                  smapper.syncWithFrameStack(stackMapIterator.getFrameStack());
 271.282 -                out.append("    case " + i).append(": ");            
 271.283 +                out.append("    X_" + i).append(": for (;;) { IF: if (gt <= " + i + ") {\n");
 271.284 +                openBraces++;
 271.285                  changeInCatch = true;
 271.286              } else {
 271.287                  debug("    /* " + i + " */ ");
 271.288 @@ -769,7 +827,7 @@
 271.289                  }
 271.290                  case opc_ldc_w:
 271.291                  case opc_ldc2_w: {
 271.292 -                    int indx = readIntArg(byteCodes, i);
 271.293 +                    int indx = readUShortArg(byteCodes, i);
 271.294                      i += 2;
 271.295                      String v = encodeConstant(indx);
 271.296                      int type = VarType.fromConstantType(jc.getTag(indx));
 271.297 @@ -800,133 +858,104 @@
 271.298                      break;
 271.299                  case opc_if_acmpeq:
 271.300                      i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
 271.301 -                                   "===");
 271.302 +                                   "===", topMostLabel);
 271.303                      break;
 271.304                  case opc_if_acmpne:
 271.305                      i = generateIf(byteCodes, i, smapper.popA(), smapper.popA(),
 271.306 -                                   "!=");
 271.307 +                                   "!==", topMostLabel);
 271.308                      break;
 271.309                  case opc_if_icmpeq:
 271.310                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.311 -                                   "==");
 271.312 +                                   "==", topMostLabel);
 271.313                      break;
 271.314                  case opc_ifeq: {
 271.315 -                    int indx = i + readIntArg(byteCodes, i);
 271.316 -                    emit(out, "if (@1 == 0) { gt = @2; continue; }",
 271.317 -                         smapper.popI(), Integer.toString(indx));
 271.318 +                    int indx = i + readShortArg(byteCodes, i);
 271.319 +                    emitIf(out, "if (@1 == 0) ",
 271.320 +                         smapper.popI(), i, indx, topMostLabel);
 271.321                      i += 2;
 271.322                      break;
 271.323                  }
 271.324                  case opc_ifne: {
 271.325 -                    int indx = i + readIntArg(byteCodes, i);
 271.326 -                    emit(out, "if (@1 != 0) { gt = @2; continue; }",
 271.327 -                         smapper.popI(), Integer.toString(indx));
 271.328 +                    int indx = i + readShortArg(byteCodes, i);
 271.329 +                    emitIf(out, "if (@1 != 0) ",
 271.330 +                         smapper.popI(), i, indx, topMostLabel);
 271.331                      i += 2;
 271.332                      break;
 271.333                  }
 271.334                  case opc_iflt: {
 271.335 -                    int indx = i + readIntArg(byteCodes, i);
 271.336 -                    emit(out, "if (@1 < 0) { gt = @2; continue; }",
 271.337 -                         smapper.popI(), Integer.toString(indx));
 271.338 +                    int indx = i + readShortArg(byteCodes, i);
 271.339 +                    emitIf(out, "if (@1 < 0) ",
 271.340 +                         smapper.popI(), i, indx, topMostLabel);
 271.341                      i += 2;
 271.342                      break;
 271.343                  }
 271.344                  case opc_ifle: {
 271.345 -                    int indx = i + readIntArg(byteCodes, i);
 271.346 -                    emit(out, "if (@1 <= 0) { gt = @2; continue; }",
 271.347 -                         smapper.popI(), Integer.toString(indx));
 271.348 +                    int indx = i + readShortArg(byteCodes, i);
 271.349 +                    emitIf(out, "if (@1 <= 0) ",
 271.350 +                         smapper.popI(), i, indx, topMostLabel);
 271.351                      i += 2;
 271.352                      break;
 271.353                  }
 271.354                  case opc_ifgt: {
 271.355 -                    int indx = i + readIntArg(byteCodes, i);
 271.356 -                    emit(out, "if (@1 > 0) { gt = @2; continue; }",
 271.357 -                         smapper.popI(), Integer.toString(indx));
 271.358 +                    int indx = i + readShortArg(byteCodes, i);
 271.359 +                    emitIf(out, "if (@1 > 0) ",
 271.360 +                         smapper.popI(), i, indx, topMostLabel);
 271.361                      i += 2;
 271.362                      break;
 271.363                  }
 271.364                  case opc_ifge: {
 271.365 -                    int indx = i + readIntArg(byteCodes, i);
 271.366 -                    emit(out, "if (@1 >= 0) { gt = @2; continue; }",
 271.367 -                         smapper.popI(), Integer.toString(indx));
 271.368 +                    int indx = i + readShortArg(byteCodes, i);
 271.369 +                    emitIf(out, "if (@1 >= 0) ",
 271.370 +                         smapper.popI(), i, indx, topMostLabel);
 271.371                      i += 2;
 271.372                      break;
 271.373                  }
 271.374                  case opc_ifnonnull: {
 271.375 -                    int indx = i + readIntArg(byteCodes, i);
 271.376 -                    emit(out, "if (@1 !== null) { gt = @2; continue; }",
 271.377 -                         smapper.popA(), Integer.toString(indx));
 271.378 +                    int indx = i + readShortArg(byteCodes, i);
 271.379 +                    emitIf(out, "if (@1 !== null) ",
 271.380 +                         smapper.popA(), i, indx, topMostLabel);
 271.381                      i += 2;
 271.382                      break;
 271.383                  }
 271.384                  case opc_ifnull: {
 271.385 -                    int indx = i + readIntArg(byteCodes, i);
 271.386 -                    emit(out, "if (@1 === null) { gt = @2; continue; }",
 271.387 -                         smapper.popA(), Integer.toString(indx));
 271.388 +                    int indx = i + readShortArg(byteCodes, i);
 271.389 +                    emitIf(out, "if (@1 === null) ",
 271.390 +                         smapper.popA(), i, indx, topMostLabel);
 271.391                      i += 2;
 271.392                      break;
 271.393                  }
 271.394                  case opc_if_icmpne:
 271.395                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.396 -                                   "!=");
 271.397 +                                   "!=", topMostLabel);
 271.398                      break;
 271.399                  case opc_if_icmplt:
 271.400                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.401 -                                   "<");
 271.402 +                                   "<", topMostLabel);
 271.403                      break;
 271.404                  case opc_if_icmple:
 271.405                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.406 -                                   "<=");
 271.407 +                                   "<=", topMostLabel);
 271.408                      break;
 271.409                  case opc_if_icmpgt:
 271.410                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.411 -                                   ">");
 271.412 +                                   ">", topMostLabel);
 271.413                      break;
 271.414                  case opc_if_icmpge:
 271.415                      i = generateIf(byteCodes, i, smapper.popI(), smapper.popI(),
 271.416 -                                   ">=");
 271.417 +                                   ">=", topMostLabel);
 271.418                      break;
 271.419                  case opc_goto: {
 271.420 -                    int indx = i + readIntArg(byteCodes, i);
 271.421 -                    emit(out, "gt = @1; continue;", Integer.toString(indx));
 271.422 +                    int indx = i + readShortArg(byteCodes, i);
 271.423 +                    goTo(out, i, indx, topMostLabel);
 271.424                      i += 2;
 271.425                      break;
 271.426                  }
 271.427                  case opc_lookupswitch: {
 271.428 -                    int table = i / 4 * 4 + 4;
 271.429 -                    int dflt = i + readInt4(byteCodes, table);
 271.430 -                    table += 4;
 271.431 -                    int n = readInt4(byteCodes, table);
 271.432 -                    table += 4;
 271.433 -                    out.append("switch (").append(smapper.popI()).append(") {\n");
 271.434 -                    while (n-- > 0) {
 271.435 -                        int cnstnt = readInt4(byteCodes, table);
 271.436 -                        table += 4;
 271.437 -                        int offset = i + readInt4(byteCodes, table);
 271.438 -                        table += 4;
 271.439 -                        out.append("  case " + cnstnt).append(": gt = " + offset).append("; continue;\n");
 271.440 -                    }
 271.441 -                    out.append("  default: gt = " + dflt).append("; continue;\n}");
 271.442 -                    i = table - 1;
 271.443 +                    i = generateLookupSwitch(i, byteCodes, smapper, topMostLabel);
 271.444                      break;
 271.445                  }
 271.446                  case opc_tableswitch: {
 271.447 -                    int table = i / 4 * 4 + 4;
 271.448 -                    int dflt = i + readInt4(byteCodes, table);
 271.449 -                    table += 4;
 271.450 -                    int low = readInt4(byteCodes, table);
 271.451 -                    table += 4;
 271.452 -                    int high = readInt4(byteCodes, table);
 271.453 -                    table += 4;
 271.454 -                    out.append("switch (").append(smapper.popI()).append(") {\n");
 271.455 -                    while (low <= high) {
 271.456 -                        int offset = i + readInt4(byteCodes, table);
 271.457 -                        table += 4;
 271.458 -                        out.append("  case " + low).append(": gt = " + offset).append("; continue;\n");
 271.459 -                        low++;
 271.460 -                    }
 271.461 -                    out.append("  default: gt = " + dflt).append("; continue;\n}");
 271.462 -                    i = table - 1;
 271.463 +                    i = generateTableSwitch(i, byteCodes, smapper, topMostLabel);
 271.464                      break;
 271.465                  }
 271.466                  case opc_invokeinterface: {
 271.467 @@ -943,7 +972,7 @@
 271.468                      i = invokeStaticMethod(byteCodes, i, smapper, true);
 271.469                      break;
 271.470                  case opc_new: {
 271.471 -                    int indx = readIntArg(byteCodes, i);
 271.472 +                    int indx = readUShortArg(byteCodes, i);
 271.473                      String ci = jc.getClassName(indx);
 271.474                      emit(out, "var @1 = new @2;",
 271.475                           smapper.pushA(), accessClass(ci.replace('/', '_')));
 271.476 @@ -953,50 +982,18 @@
 271.477                  }
 271.478                  case opc_newarray:
 271.479                      int atype = readUByte(byteCodes, ++i);
 271.480 -                    String jvmType;
 271.481 -                    switch (atype) {
 271.482 -                        case 4: jvmType = "[Z"; break;
 271.483 -                        case 5: jvmType = "[C"; break;
 271.484 -                        case 6: jvmType = "[F"; break;
 271.485 -                        case 7: jvmType = "[D"; break;
 271.486 -                        case 8: jvmType = "[B"; break;
 271.487 -                        case 9: jvmType = "[S"; break;
 271.488 -                        case 10: jvmType = "[I"; break;
 271.489 -                        case 11: jvmType = "[J"; break;
 271.490 -                        default: throw new IllegalStateException("Array type: " + atype);
 271.491 -                    }
 271.492 -                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
 271.493 -                         smapper.popI(), smapper.pushA(), jvmType);
 271.494 +                    generateNewArray(atype, smapper);
 271.495                      break;
 271.496                  case opc_anewarray: {
 271.497 -                    int type = readIntArg(byteCodes, i);
 271.498 +                    int type = readUShortArg(byteCodes, i);
 271.499                      i += 2;
 271.500 -                    String typeName = jc.getClassName(type);
 271.501 -                    if (typeName.startsWith("[")) {
 271.502 -                        typeName = "[" + typeName;
 271.503 -                    } else {
 271.504 -                        typeName = "[L" + typeName + ";";
 271.505 -                    }
 271.506 -                    emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
 271.507 -                         smapper.popI(), smapper.pushA(), typeName);
 271.508 +                    generateANewArray(type, smapper);
 271.509                      break;
 271.510                  }
 271.511                  case opc_multianewarray: {
 271.512 -                    int type = readIntArg(byteCodes, i);
 271.513 +                    int type = readUShortArg(byteCodes, i);
 271.514                      i += 2;
 271.515 -                    String typeName = jc.getClassName(type);
 271.516 -                    int dim = readUByte(byteCodes, ++i);
 271.517 -                    StringBuilder dims = new StringBuilder();
 271.518 -                    dims.append('[');
 271.519 -                    for (int d = 0; d < dim; d++) {
 271.520 -                        if (d != 0) {
 271.521 -                            dims.append(",");
 271.522 -                        }
 271.523 -                        dims.append(smapper.popI());
 271.524 -                    }
 271.525 -                    dims.append(']');
 271.526 -                    emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
 271.527 -                         dims.toString(), smapper.pushA(), typeName);
 271.528 +                    i = generateMultiANewArray(type, byteCodes, i, smapper);
 271.529                      break;
 271.530                  }
 271.531                  case opc_arraylength:
 271.532 @@ -1210,11 +1207,11 @@
 271.533                  case opc_sipush:
 271.534                      emit(out, "var @1 = @2;",
 271.535                           smapper.pushI(),
 271.536 -                         Integer.toString(readIntArg(byteCodes, i)));
 271.537 +                         Integer.toString(readShortArg(byteCodes, i)));
 271.538                      i += 2;
 271.539                      break;
 271.540                  case opc_getfield: {
 271.541 -                    int indx = readIntArg(byteCodes, i);
 271.542 +                    int indx = readUShortArg(byteCodes, i);
 271.543                      String[] fi = jc.getFieldInfoName(indx);
 271.544                      final int type = VarType.fromFieldType(fi[2].charAt(0));
 271.545                      final String mangleClass = mangleSig(fi[0]);
 271.546 @@ -1227,7 +1224,7 @@
 271.547                      break;
 271.548                  }
 271.549                  case opc_putfield: {
 271.550 -                    int indx = readIntArg(byteCodes, i);
 271.551 +                    int indx = readUShortArg(byteCodes, i);
 271.552                      String[] fi = jc.getFieldInfoName(indx);
 271.553                      final int type = VarType.fromFieldType(fi[2].charAt(0));
 271.554                      final String mangleClass = mangleSig(fi[0]);
 271.555 @@ -1241,10 +1238,10 @@
 271.556                      break;
 271.557                  }
 271.558                  case opc_getstatic: {
 271.559 -                    int indx = readIntArg(byteCodes, i);
 271.560 +                    int indx = readUShortArg(byteCodes, i);
 271.561                      String[] fi = jc.getFieldInfoName(indx);
 271.562                      final int type = VarType.fromFieldType(fi[2].charAt(0));
 271.563 -                    emit(out, "var @1 = @2(false).constructor.@3;",
 271.564 +                    emit(out, "var @1 = @2(false)._@3();",
 271.565                           smapper.pushT(type),
 271.566                           accessClass(fi[0].replace('/', '_')), fi[1]);
 271.567                      i += 2;
 271.568 @@ -1252,10 +1249,10 @@
 271.569                      break;
 271.570                  }
 271.571                  case opc_putstatic: {
 271.572 -                    int indx = readIntArg(byteCodes, i);
 271.573 +                    int indx = readUShortArg(byteCodes, i);
 271.574                      String[] fi = jc.getFieldInfoName(indx);
 271.575                      final int type = VarType.fromFieldType(fi[2].charAt(0));
 271.576 -                    emit(out, "@1(false).constructor.@2 = @3;",
 271.577 +                    emit(out, "@1(false)._@2(@3);",
 271.578                           accessClass(fi[0].replace('/', '_')), fi[1],
 271.579                           smapper.popT(type));
 271.580                      i += 2;
 271.581 @@ -1263,33 +1260,14 @@
 271.582                      break;
 271.583                  }
 271.584                  case opc_checkcast: {
 271.585 -                    int indx = readIntArg(byteCodes, i);
 271.586 -                    final String type = jc.getClassName(indx);
 271.587 -                    if (!type.startsWith("[")) {
 271.588 -                        emit(out,
 271.589 -                             "if (@1 !== null && !@1.$instOf_@2) throw {};",
 271.590 -                             smapper.getA(0), type.replace('/', '_'));
 271.591 -                    } else {
 271.592 -                        emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
 271.593 -                             smapper.getA(0), type
 271.594 -                        );
 271.595 -                    }
 271.596 +                    int indx = readUShortArg(byteCodes, i);
 271.597 +                    generateCheckcast(indx, smapper);
 271.598                      i += 2;
 271.599                      break;
 271.600                  }
 271.601                  case opc_instanceof: {
 271.602 -                    int indx = readIntArg(byteCodes, i);
 271.603 -                    final String type = jc.getClassName(indx);
 271.604 -                    if (!type.startsWith("[")) {
 271.605 -                        emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
 271.606 -                             smapper.popA(), smapper.pushI(),
 271.607 -                             type.replace('/', '_'));
 271.608 -                    } else {
 271.609 -                        emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
 271.610 -                            smapper.popA(), smapper.pushI(),
 271.611 -                            type
 271.612 -                        );
 271.613 -                    }
 271.614 +                    int indx = readUShortArg(byteCodes, i);
 271.615 +                    generateInstanceOf(indx, smapper);
 271.616                      i += 2;
 271.617                      break;
 271.618                  }
 271.619 @@ -1325,37 +1303,29 @@
 271.620                  }
 271.621              }
 271.622              if (debug(" //")) {
 271.623 -                for (int j = prev; j <= i; j++) {
 271.624 -                    out.append(" ");
 271.625 -                    final int cc = readUByte(byteCodes, j);
 271.626 -                    out.append(Integer.toString(cc));
 271.627 -                }
 271.628 +                generateByteCodeComment(prev, i, byteCodes);
 271.629              }
 271.630              out.append("\n");            
 271.631          }
 271.632          if (previousTrap != null) {
 271.633 -            generateCatch(previousTrap);
 271.634 +            generateCatch(previousTrap, byteCodes.length, topMostLabel);
 271.635          }
 271.636 -        out.append("  }\n");
 271.637 -        out.append("};");
 271.638 +        out.append("\n    }\n");
 271.639 +        while (openBraces-- > 0) {
 271.640 +            out.append('}');
 271.641 +        }
 271.642 +        out.append("\n};");
 271.643      }
 271.644  
 271.645 -    private int generateIf(byte[] byteCodes, int i,
 271.646 -                           final Variable v2, final Variable v1,
 271.647 -                           final String test) throws IOException {
 271.648 -        int indx = i + readIntArg(byteCodes, i);
 271.649 +    private int generateIf(byte[] byteCodes, int i, final Variable v2, final Variable v1, final String test, int topMostLabel) throws IOException {
 271.650 +        int indx = i + readShortArg(byteCodes, i);
 271.651          out.append("if (").append(v1)
 271.652             .append(' ').append(test).append(' ')
 271.653 -           .append(v2).append(") { gt = " + indx)
 271.654 -           .append("; continue; }");
 271.655 +           .append(v2).append(") ");
 271.656 +        goTo(out, i, indx, topMostLabel);
 271.657          return i + 2;
 271.658      }
 271.659 -
 271.660 -    private int readIntArg(byte[] byteCodes, int offsetInstruction) {
 271.661 -        final int indxHi = byteCodes[offsetInstruction + 1] << 8;
 271.662 -        final int indxLo = byteCodes[offsetInstruction + 2];
 271.663 -        return (indxHi & 0xffffff00) | (indxLo & 0xff);
 271.664 -    }
 271.665 +    
 271.666      private int readInt4(byte[] byteCodes, int offset) {
 271.667          final int d = byteCodes[offset + 0] << 24;
 271.668          final int c = byteCodes[offset + 1] << 16;
 271.669 @@ -1363,18 +1333,25 @@
 271.670          final int a = byteCodes[offset + 3];
 271.671          return (d & 0xff000000) | (c & 0xff0000) | (b & 0xff00) | (a & 0xff);
 271.672      }
 271.673 -    private int readUByte(byte[] byteCodes, int offset) {
 271.674 +    private static int readUByte(byte[] byteCodes, int offset) {
 271.675          return byteCodes[offset] & 0xff;
 271.676      }
 271.677  
 271.678 -    private int readUShort(byte[] byteCodes, int offset) {
 271.679 +    private static int readUShort(byte[] byteCodes, int offset) {
 271.680          return ((byteCodes[offset] & 0xff) << 8)
 271.681                      | (byteCodes[offset + 1] & 0xff);
 271.682      }
 271.683 +    private static int readUShortArg(byte[] byteCodes, int offsetInstruction) {
 271.684 +        return readUShort(byteCodes, offsetInstruction + 1);
 271.685 +    }
 271.686  
 271.687 -    private int readShort(byte[] byteCodes, int offset) {
 271.688 -        return (byteCodes[offset] << 8)
 271.689 -                    | (byteCodes[offset + 1] & 0xff);
 271.690 +    private static int readShort(byte[] byteCodes, int offset) {
 271.691 +        int signed = byteCodes[offset];
 271.692 +        byte b0 = (byte)signed;
 271.693 +        return (b0 << 8) | (byteCodes[offset + 1] & 0xff);
 271.694 +    }
 271.695 +    private static int readShortArg(byte[] byteCodes, int offsetInstruction) {
 271.696 +        return readShort(byteCodes, offsetInstruction + 1);
 271.697      }
 271.698  
 271.699      private static void countArgs(String descriptor, char[] returnType, StringBuilder sig, StringBuilder cnt) {
 271.700 @@ -1502,7 +1479,7 @@
 271.701  
 271.702      private int invokeStaticMethod(byte[] byteCodes, int i, final StackMapper mapper, boolean isStatic)
 271.703      throws IOException {
 271.704 -        int methodIndex = readIntArg(byteCodes, i);
 271.705 +        int methodIndex = readUShortArg(byteCodes, i);
 271.706          String[] mi = jc.getFieldInfoName(methodIndex);
 271.707          char[] returnType = { 'V' };
 271.708          StringBuilder cnt = new StringBuilder();
 271.709 @@ -1547,7 +1524,7 @@
 271.710      }
 271.711      private int invokeVirtualMethod(byte[] byteCodes, int i, final StackMapper mapper)
 271.712      throws IOException {
 271.713 -        int methodIndex = readIntArg(byteCodes, i);
 271.714 +        int methodIndex = readUShortArg(byteCodes, i);
 271.715          String[] mi = jc.getFieldInfoName(methodIndex);
 271.716          char[] returnType = { 'V' };
 271.717          StringBuilder cnt = new StringBuilder();
 271.718 @@ -1614,12 +1591,13 @@
 271.719          return s;
 271.720      }
 271.721  
 271.722 -    private String javaScriptBody(String prefix, MethodData m, boolean isStatic) throws IOException {
 271.723 +    private String javaScriptBody(String destObject, MethodData m, boolean isStatic) throws IOException {
 271.724          byte[] arr = m.findAnnotationData(true);
 271.725          if (arr == null) {
 271.726              return null;
 271.727          }
 271.728          final String jvmType = "Lorg/apidesign/bck2brwsr/core/JavaScriptBody;";
 271.729 +        final String htmlType = "Lnet/java/html/js/JavaScriptBody;";
 271.730          class P extends AnnotationParser {
 271.731              public P() {
 271.732                  super(false, true);
 271.733 @@ -1628,6 +1606,7 @@
 271.734              int cnt;
 271.735              String[] args = new String[30];
 271.736              String body;
 271.737 +            boolean javacall;
 271.738              
 271.739              @Override
 271.740              protected void visitAttr(String type, String attr, String at, String value) {
 271.741 @@ -1640,6 +1619,17 @@
 271.742                          throw new IllegalArgumentException(attr);
 271.743                      }
 271.744                  }
 271.745 +                if (type.equals(htmlType)) {
 271.746 +                    if ("body".equals(attr)) {
 271.747 +                        body = value;
 271.748 +                    } else if ("args".equals(attr)) {
 271.749 +                        args[cnt++] = value;
 271.750 +                    } else if ("javacall".equals(attr)) {
 271.751 +                        javacall = "1".equals(value);
 271.752 +                    } else {
 271.753 +                        throw new IllegalArgumentException(attr);
 271.754 +                    }
 271.755 +                }
 271.756              }
 271.757          }
 271.758          P p = new P();
 271.759 @@ -1649,7 +1639,7 @@
 271.760          }
 271.761          StringBuilder cnt = new StringBuilder();
 271.762          final String mn = findMethodName(m, cnt);
 271.763 -        out.append(prefix).append(mn);
 271.764 +        out.append(destObject).append(".").append(mn);
 271.765          out.append(" = function(");
 271.766          String space = "";
 271.767          int index = 0;
 271.768 @@ -1659,10 +1649,121 @@
 271.769              index++;
 271.770          }
 271.771          out.append(") {").append("\n");
 271.772 -        out.append(p.body);
 271.773 +        if (p.javacall) {
 271.774 +            int lastSlash = jc.getClassName().lastIndexOf('/');
 271.775 +            final String pkg = jc.getClassName().substring(0, lastSlash);
 271.776 +            out.append(mangleCallbacks(pkg, p.body));
 271.777 +            requireReference(pkg + "/$JsCallbacks$");
 271.778 +        } else {
 271.779 +            out.append(p.body);
 271.780 +        }
 271.781          out.append("\n}\n");
 271.782          return mn;
 271.783      }
 271.784 +    
 271.785 +    private static CharSequence mangleCallbacks(String pkgName, String body) {
 271.786 +        StringBuilder sb = new StringBuilder();
 271.787 +        int pos = 0;
 271.788 +        for (;;) {
 271.789 +            int next = body.indexOf(".@", pos);
 271.790 +            if (next == -1) {
 271.791 +                sb.append(body.substring(pos));
 271.792 +                body = sb.toString();
 271.793 +                break;
 271.794 +            }
 271.795 +            int ident = next;
 271.796 +            while (ident > 0) {
 271.797 +                if (!Character.isJavaIdentifierPart(body.charAt(--ident))) {
 271.798 +                    ident++;
 271.799 +                    break;
 271.800 +                }
 271.801 +            }
 271.802 +            String refId = body.substring(ident, next);
 271.803 +
 271.804 +            sb.append(body.substring(pos, ident));
 271.805 +
 271.806 +            int sigBeg = body.indexOf('(', next);
 271.807 +            int sigEnd = body.indexOf(')', sigBeg);
 271.808 +            int colon4 = body.indexOf("::", next);
 271.809 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
 271.810 +                throw new IllegalStateException("Malformed body " + body);
 271.811 +            }
 271.812 +            String fqn = body.substring(next + 2, colon4);
 271.813 +            String method = body.substring(colon4 + 2, sigBeg);
 271.814 +            String params = body.substring(sigBeg, sigEnd + 1);
 271.815 +
 271.816 +            int paramBeg = body.indexOf('(', sigEnd + 1);
 271.817 +            
 271.818 +            sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
 271.819 +            sb.append(mangle(fqn, method, params, false));
 271.820 +            sb.append("(").append(refId);
 271.821 +            if (body.charAt(paramBeg + 1) != ')') {
 271.822 +                sb.append(",");
 271.823 +            }
 271.824 +            pos = paramBeg + 1;
 271.825 +        }
 271.826 +        sb = null;
 271.827 +        pos = 0;
 271.828 +        for (;;) {
 271.829 +            int next = body.indexOf("@", pos);
 271.830 +            if (next == -1) {
 271.831 +                if (sb == null) {
 271.832 +                    return body;
 271.833 +                }
 271.834 +                sb.append(body.substring(pos));
 271.835 +                return sb;
 271.836 +            }
 271.837 +            if (sb == null) {
 271.838 +                sb = new StringBuilder();
 271.839 +            }
 271.840 +
 271.841 +            sb.append(body.substring(pos, next));
 271.842 +
 271.843 +            int sigBeg = body.indexOf('(', next);
 271.844 +            int sigEnd = body.indexOf(')', sigBeg);
 271.845 +            int colon4 = body.indexOf("::", next);
 271.846 +            if (sigBeg == -1 || sigEnd == -1 || colon4 == -1) {
 271.847 +                throw new IllegalStateException("Malformed body " + body);
 271.848 +            }
 271.849 +            String fqn = body.substring(next + 1, colon4);
 271.850 +            String method = body.substring(colon4 + 2, sigBeg);
 271.851 +            String params = body.substring(sigBeg, sigEnd + 1);
 271.852 +
 271.853 +            int paramBeg = body.indexOf('(', sigEnd + 1);
 271.854 +            
 271.855 +            sb.append("vm.").append(pkgName.replace('/', '_')).append("_$JsCallbacks$(false)._VM().");
 271.856 +            sb.append(mangle(fqn, method, params, true));
 271.857 +            sb.append("(");
 271.858 +            pos = paramBeg + 1;
 271.859 +        }
 271.860 +    }
 271.861 +    private static String mangle(String fqn, String method, String params, boolean isStatic) {
 271.862 +        if (params.startsWith("(")) {
 271.863 +            params = params.substring(1);
 271.864 +        }
 271.865 +        if (params.endsWith(")")) {
 271.866 +            params = params.substring(0, params.length() - 1);
 271.867 +        }
 271.868 +        StringBuilder sb = new StringBuilder();
 271.869 +        final String rfqn = replace(fqn);
 271.870 +        final String rm = replace(method);
 271.871 +        final String rp = replace(params);
 271.872 +        sb.append(rfqn).append("$").append(rm).
 271.873 +            append('$').append(rp).append("__Ljava_lang_Object_2");
 271.874 +        if (!isStatic) {
 271.875 +            sb.append('L').append(rfqn).append("_2");
 271.876 +        }
 271.877 +        sb.append(rp);
 271.878 +        return sb.toString();
 271.879 +    }
 271.880 +
 271.881 +    private static String replace(String orig) {
 271.882 +        return orig.replace("_", "_1").
 271.883 +            replace(";", "_2").
 271.884 +            replace("[", "_3").
 271.885 +            replace('.', '_').replace('/', '_');
 271.886 +    }
 271.887 +    
 271.888      private static String className(ClassData jc) {
 271.889          //return jc.getName().getInternalName().replace('/', '_');
 271.890          return jc.getClassName().replace('/', '_');
 271.891 @@ -1822,7 +1923,7 @@
 271.892          out.append(format, processed, length);
 271.893      }
 271.894  
 271.895 -    private void generateCatch(TrapData[] traps) throws IOException {
 271.896 +    private void generateCatch(TrapData[] traps, int current, int topMostLabel) throws IOException {
 271.897          out.append("} catch (e) {\n");
 271.898          int finallyPC = -1;
 271.899          for (TrapData e : traps) {
 271.900 @@ -1832,19 +1933,11 @@
 271.901              if (e.catch_cpx != 0) { //not finally
 271.902                  final String classInternalName = jc.getClassName(e.catch_cpx);
 271.903                  addReference(classInternalName);
 271.904 -                if ("java/lang/Throwable".equals(classInternalName)) {
 271.905 -                    out.append("if (e.$instOf_java_lang_Throwable) {");
 271.906 -                    out.append("  var stA0 = e;");
 271.907 -                    out.append("} else {");
 271.908 -                    out.append("  var stA0 = vm.java_lang_Throwable(true);");
 271.909 -                    out.append("  vm.java_lang_Throwable.cons__VLjava_lang_String_2.call(stA0, e.toString());");
 271.910 -                    out.append("}");
 271.911 -                    out.append("gt=" + e.handler_pc + "; continue;");
 271.912 -                } else {
 271.913 -                    out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
 271.914 -                    out.append("gt=" + e.handler_pc + "; var stA0 = e; continue;");
 271.915 -                    out.append("}\n");
 271.916 -                }
 271.917 +                out.append("e = vm.java_lang_Throwable(false).bck2BrwsrCnvrt(e);");
 271.918 +                out.append("if (e.$instOf_" + classInternalName.replace('/', '_') + ") {");
 271.919 +                out.append("var stA0 = e;");
 271.920 +                goTo(out, current, e.handler_pc, topMostLabel);
 271.921 +                out.append("}\n");
 271.922              } else {
 271.923                  finallyPC = e.handler_pc;
 271.924              }
 271.925 @@ -1852,8 +1945,152 @@
 271.926          if (finallyPC == -1) {
 271.927              out.append("throw e;");
 271.928          } else {
 271.929 -            out.append("gt=" + finallyPC + "; var stA0 = e; continue;");
 271.930 +            out.append("var stA0 = e;");
 271.931 +            goTo(out, current, finallyPC, topMostLabel);
 271.932          }
 271.933          out.append("\n}");
 271.934      }
 271.935 +
 271.936 +    private static void goTo(Appendable out, int current, int to, int canBack) throws IOException {
 271.937 +        if (to < current) {
 271.938 +            if (canBack < to) {
 271.939 +                out.append("{ gt = 0; continue X_" + to + "; }");
 271.940 +            } else {
 271.941 +                out.append("{ gt = " + to + "; continue X_0; }");
 271.942 +            }
 271.943 +        } else {
 271.944 +            out.append("{ gt = " + to + "; break IF; }");
 271.945 +        }
 271.946 +    }
 271.947 +
 271.948 +    private static void emitIf(
 271.949 +        Appendable out, String pattern, Variable param, 
 271.950 +        int current, int to, int canBack
 271.951 +    ) throws IOException {
 271.952 +        emit(out, pattern, param);
 271.953 +        goTo(out, current, to, canBack);
 271.954 +    }
 271.955 +
 271.956 +    private void generateNewArray(int atype, final StackMapper smapper) throws IOException, IllegalStateException {
 271.957 +        String jvmType;
 271.958 +        switch (atype) {
 271.959 +            case 4: jvmType = "[Z"; break;
 271.960 +            case 5: jvmType = "[C"; break;
 271.961 +            case 6: jvmType = "[F"; break;
 271.962 +            case 7: jvmType = "[D"; break;
 271.963 +            case 8: jvmType = "[B"; break;
 271.964 +            case 9: jvmType = "[S"; break;
 271.965 +            case 10: jvmType = "[I"; break;
 271.966 +            case 11: jvmType = "[J"; break;
 271.967 +            default: throw new IllegalStateException("Array type: " + atype);
 271.968 +        }
 271.969 +        emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(true, '@3', @1);",
 271.970 +             smapper.popI(), smapper.pushA(), jvmType);
 271.971 +    }
 271.972 +
 271.973 +    private void generateANewArray(int type, final StackMapper smapper) throws IOException {
 271.974 +        String typeName = jc.getClassName(type);
 271.975 +        if (typeName.startsWith("[")) {
 271.976 +            typeName = "[" + typeName;
 271.977 +        } else {
 271.978 +            typeName = "[L" + typeName + ";";
 271.979 +        }
 271.980 +        emit(out, "var @2 = Array.prototype.newArray__Ljava_lang_Object_2ZLjava_lang_String_2I(false, '@3', @1);",
 271.981 +             smapper.popI(), smapper.pushA(), typeName);
 271.982 +    }
 271.983 +
 271.984 +    private int generateMultiANewArray(int type, final byte[] byteCodes, int i, final StackMapper smapper) throws IOException {
 271.985 +        String typeName = jc.getClassName(type);
 271.986 +        int dim = readUByte(byteCodes, ++i);
 271.987 +        StringBuilder dims = new StringBuilder();
 271.988 +        dims.append('[');
 271.989 +        for (int d = 0; d < dim; d++) {
 271.990 +            if (d != 0) {
 271.991 +                dims.insert(1, ",");
 271.992 +            }
 271.993 +            dims.insert(1, smapper.popI());
 271.994 +        }
 271.995 +        dims.append(']');
 271.996 +        emit(out, "var @2 = Array.prototype.multiNewArray__Ljava_lang_Object_2Ljava_lang_String_2_3II('@3', @1, 0);",
 271.997 +             dims.toString(), smapper.pushA(), typeName);
 271.998 +        return i;
 271.999 +    }
271.1000 +
271.1001 +    private int generateTableSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
271.1002 +        int table = i / 4 * 4 + 4;
271.1003 +        int dflt = i + readInt4(byteCodes, table);
271.1004 +        table += 4;
271.1005 +        int low = readInt4(byteCodes, table);
271.1006 +        table += 4;
271.1007 +        int high = readInt4(byteCodes, table);
271.1008 +        table += 4;
271.1009 +        out.append("switch (").append(smapper.popI()).append(") {\n");
271.1010 +        while (low <= high) {
271.1011 +            int offset = i + readInt4(byteCodes, table);
271.1012 +            table += 4;
271.1013 +            out.append("  case " + low).append(":"); goTo(out, i, offset, topMostLabel); out.append('\n');
271.1014 +            low++;
271.1015 +        }
271.1016 +        out.append("  default: ");
271.1017 +        goTo(out, i, dflt, topMostLabel);
271.1018 +        out.append("\n}");
271.1019 +        i = table - 1;
271.1020 +        return i;
271.1021 +    }
271.1022 +
271.1023 +    private int generateLookupSwitch(int i, final byte[] byteCodes, final StackMapper smapper, int topMostLabel) throws IOException {
271.1024 +        int table = i / 4 * 4 + 4;
271.1025 +        int dflt = i + readInt4(byteCodes, table);
271.1026 +        table += 4;
271.1027 +        int n = readInt4(byteCodes, table);
271.1028 +        table += 4;
271.1029 +        out.append("switch (").append(smapper.popI()).append(") {\n");
271.1030 +        while (n-- > 0) {
271.1031 +            int cnstnt = readInt4(byteCodes, table);
271.1032 +            table += 4;
271.1033 +            int offset = i + readInt4(byteCodes, table);
271.1034 +            table += 4;
271.1035 +            out.append("  case " + cnstnt).append(": "); goTo(out, i, offset, topMostLabel); out.append('\n');
271.1036 +        }
271.1037 +        out.append("  default: ");
271.1038 +        goTo(out, i, dflt, topMostLabel);
271.1039 +        out.append("\n}");
271.1040 +        i = table - 1;
271.1041 +        return i;
271.1042 +    }
271.1043 +
271.1044 +    private void generateInstanceOf(int indx, final StackMapper smapper) throws IOException {
271.1045 +        final String type = jc.getClassName(indx);
271.1046 +        if (!type.startsWith("[")) {
271.1047 +            emit(out, "var @2 = @1 != null && @1.$instOf_@3 ? 1 : 0;",
271.1048 +                 smapper.popA(), smapper.pushI(),
271.1049 +                 type.replace('/', '_'));
271.1050 +        } else {
271.1051 +            emit(out, "var @2 = vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@3').isInstance__ZLjava_lang_Object_2(@1);",
271.1052 +                smapper.popA(), smapper.pushI(),
271.1053 +                type
271.1054 +            );
271.1055 +        }
271.1056 +    }
271.1057 +
271.1058 +    private void generateCheckcast(int indx, final StackMapper smapper) throws IOException {
271.1059 +        final String type = jc.getClassName(indx);
271.1060 +        if (!type.startsWith("[")) {
271.1061 +            emit(out,
271.1062 +                 "if (@1 !== null && !@1.$instOf_@2) throw vm.java_lang_ClassCastException(true);",
271.1063 +                 smapper.getA(0), type.replace('/', '_'));
271.1064 +        } else {
271.1065 +            emit(out, "vm.java_lang_Class(false).forName__Ljava_lang_Class_2Ljava_lang_String_2('@2').cast__Ljava_lang_Object_2Ljava_lang_Object_2(@1);",
271.1066 +                 smapper.getA(0), type
271.1067 +            );
271.1068 +        }
271.1069 +    }
271.1070 +
271.1071 +    private void generateByteCodeComment(int prev, int i, final byte[] byteCodes) throws IOException {
271.1072 +        for (int j = prev; j <= i; j++) {
271.1073 +            out.append(" ");
271.1074 +            final int cc = readUByte(byteCodes, j);
271.1075 +            out.append(Integer.toString(cc));
271.1076 +        }
271.1077 +    }
271.1078  }
   272.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   272.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ClosureWrapper.java	Mon Oct 07 14:20:58 2013 +0200
   272.3 @@ -0,0 +1,334 @@
   272.4 +/**
   272.5 + * Back 2 Browser Bytecode Translator
   272.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   272.7 + *
   272.8 + * This program is free software: you can redistribute it and/or modify
   272.9 + * it under the terms of the GNU General Public License as published by
  272.10 + * the Free Software Foundation, version 2 of the License.
  272.11 + *
  272.12 + * This program is distributed in the hope that it will be useful,
  272.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  272.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  272.15 + * GNU General Public License for more details.
  272.16 + *
  272.17 + * You should have received a copy of the GNU General Public License
  272.18 + * along with this program. Look for COPYING file in the top folder.
  272.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  272.20 + */
  272.21 +package org.apidesign.vm4brwsr;
  272.22 +
  272.23 +import com.google.javascript.jscomp.CommandLineRunner;
  272.24 +import com.google.javascript.jscomp.SourceFile;
  272.25 +import java.io.IOException;
  272.26 +import java.io.OutputStream;
  272.27 +import java.io.PrintStream;
  272.28 +import java.util.ArrayList;
  272.29 +import java.util.Arrays;
  272.30 +import java.util.Collection;
  272.31 +import java.util.Collections;
  272.32 +import java.util.List;
  272.33 +import org.apidesign.bck2brwsr.core.ExtraJavaScript;
  272.34 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
  272.35 +import org.apidesign.vm4brwsr.ByteCodeParser.FieldData;
  272.36 +import org.apidesign.vm4brwsr.ByteCodeParser.MethodData;
  272.37 +
  272.38 +/**
  272.39 + *
  272.40 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  272.41 + */
  272.42 +@ExtraJavaScript(processByteCode = false, resource="")
  272.43 +final class ClosureWrapper extends CommandLineRunner {
  272.44 +    private static final String[] ARGS = { "--compilation_level", "SIMPLE_OPTIMIZATIONS", "--js", "bck2brwsr-raw.js" /*, "--debug", "--formatting", "PRETTY_PRINT" */ };
  272.45 +
  272.46 +    private final ClosuresObfuscationDelegate obfuscationDelegate;
  272.47 +    private final Bck2Brwsr.Resources res;
  272.48 +    private final StringArray classes;
  272.49 +
  272.50 +    private String compiledCode;
  272.51 +    private String externsCode;
  272.52 +
  272.53 +    private ClosureWrapper(Appendable out, 
  272.54 +                           String compilationLevel,
  272.55 +                           ClosuresObfuscationDelegate obfuscationDelegate,
  272.56 +                           Bck2Brwsr.Resources res, StringArray classes) {
  272.57 +        super(
  272.58 +            generateArguments(compilationLevel),
  272.59 +            new PrintStream(new APS(out)), System.err
  272.60 +        );
  272.61 +        this.obfuscationDelegate = obfuscationDelegate;
  272.62 +        this.res = res;
  272.63 +        this.classes = classes;
  272.64 +    }
  272.65 +
  272.66 +    @Override
  272.67 +    protected List<SourceFile> createInputs(List<String> files, boolean allowStdIn) throws FlagUsageException, IOException {
  272.68 +        if (files.size() != 1 || !"bck2brwsr-raw.js".equals(files.get(0))) {
  272.69 +            throw new IOException("Unexpected files: " + files);
  272.70 +        }
  272.71 +        return Collections.nCopies(
  272.72 +                   1,
  272.73 +                   SourceFile.fromGenerator(
  272.74 +                       "bck2brwsr-raw.js",
  272.75 +                       new SourceFile.Generator() {
  272.76 +                           @Override
  272.77 +                           public String getCode() {
  272.78 +                               return getCompiledCode();
  272.79 +                           }
  272.80 +                       }));
  272.81 +    }
  272.82 +
  272.83 +
  272.84 +    @Override
  272.85 +    protected List<SourceFile> createExterns()
  272.86 +            throws FlagUsageException, IOException {
  272.87 +        final List<SourceFile> externsFiles =
  272.88 +                new ArrayList<SourceFile>(super.createExterns());
  272.89 +
  272.90 +        externsFiles.add(
  272.91 +                SourceFile.fromGenerator(
  272.92 +                        "bck2brwsr_externs.js",
  272.93 +                        new SourceFile.Generator() {
  272.94 +                            @Override
  272.95 +                            public String getCode() {
  272.96 +                                return getExternsCode();
  272.97 +                            }
  272.98 +                        }));
  272.99 +        return externsFiles;
 272.100 +    }
 272.101 +
 272.102 +    private String getCompiledCode() {
 272.103 +        if (compiledCode == null) {
 272.104 +            StringBuilder sb = new StringBuilder();
 272.105 +            try {
 272.106 +                VM.compile(res, sb, classes, obfuscationDelegate);
 272.107 +                compiledCode = sb.toString();
 272.108 +            } catch (IOException ex) {
 272.109 +                compiledCode = ex.getMessage();
 272.110 +            }
 272.111 +        }
 272.112 +        return compiledCode;
 272.113 +    }
 272.114 +
 272.115 +    private String getExternsCode() {
 272.116 +        if (externsCode == null) {
 272.117 +            // need compiled code at this point
 272.118 +            getCompiledCode();
 272.119 +
 272.120 +            final StringBuilder sb = new StringBuilder("function RAW() {};\n");
 272.121 +            for (final String extern: obfuscationDelegate.getExterns()) {
 272.122 +                sb.append("RAW.prototype.").append(extern).append(";\n");
 272.123 +            }
 272.124 +            externsCode = sb.toString();
 272.125 +        }
 272.126 +        return externsCode;
 272.127 +    }
 272.128 +
 272.129 +    private static final class APS extends OutputStream {
 272.130 +        private final Appendable out;
 272.131 +
 272.132 +        public APS(Appendable out) {
 272.133 +            this.out = out;
 272.134 +        }
 272.135 +        @Override
 272.136 +        public void write(int b) throws IOException {
 272.137 +            out.append((char)b);
 272.138 +        }
 272.139 +    }
 272.140 +
 272.141 +    private static String[] generateArguments(String compilationLevel) {
 272.142 +        String[] finalArgs = ARGS.clone();
 272.143 +        finalArgs[1] = compilationLevel;
 272.144 +
 272.145 +        return finalArgs;
 272.146 +    }
 272.147 +
 272.148 +    static int produceTo(Appendable w, ObfuscationLevel obfuscationLevel, Bck2Brwsr.Resources resources, StringArray arr) throws IOException {
 272.149 +        ClosureWrapper cw = create(w, obfuscationLevel, resources, arr);
 272.150 +        try {
 272.151 +            return cw.doRun();
 272.152 +        } catch (FlagUsageException ex) {
 272.153 +            throw new IOException(ex);
 272.154 +        }
 272.155 +    }
 272.156 +
 272.157 +    private static ClosureWrapper create(Appendable w,
 272.158 +                                         ObfuscationLevel obfuscationLevel,
 272.159 +                                         Bck2Brwsr.Resources resources,
 272.160 +                                         StringArray arr) {
 272.161 +        switch (obfuscationLevel) {
 272.162 +            case MINIMAL:
 272.163 +                return new ClosureWrapper(w, "SIMPLE_OPTIMIZATIONS",
 272.164 +                                          new SimpleObfuscationDelegate(),
 272.165 +                                          resources, arr);
 272.166 +/*                
 272.167 +            case MEDIUM:
 272.168 +                return new ClosureWrapper(w, "ADVANCED_OPTIMIZATIONS",
 272.169 +                                          new MediumObfuscationDelegate(),
 272.170 +                                          resources, arr);
 272.171 +*/
 272.172 +            case FULL:
 272.173 +                return new ClosureWrapper(w, "ADVANCED_OPTIMIZATIONS",
 272.174 +                                          new FullObfuscationDelegate(),
 272.175 +                                          resources, arr);
 272.176 +            default:
 272.177 +                throw new IllegalArgumentException(
 272.178 +                        "Unsupported level: " + obfuscationLevel);
 272.179 +        }
 272.180 +    }
 272.181 +
 272.182 +    private static abstract class ClosuresObfuscationDelegate
 272.183 +            extends ObfuscationDelegate {
 272.184 +        public abstract Collection<String> getExterns();
 272.185 +    }
 272.186 +
 272.187 +    private static final class SimpleObfuscationDelegate
 272.188 +            extends ClosuresObfuscationDelegate {
 272.189 +        @Override
 272.190 +        public void exportJSProperty(Appendable out,
 272.191 +                                     String destObject,
 272.192 +                                     String propertyName) throws IOException {
 272.193 +        }
 272.194 +
 272.195 +        @Override
 272.196 +        public void exportClass(Appendable out,
 272.197 +                                String destObject,
 272.198 +                                String mangledName,
 272.199 +                                ClassData classData) throws IOException {
 272.200 +        }
 272.201 +
 272.202 +        @Override
 272.203 +        public void exportMethod(Appendable out,
 272.204 +                                 String destObject,
 272.205 +                                 String mangledName,
 272.206 +                                 MethodData methodData) throws IOException {
 272.207 +        }
 272.208 +
 272.209 +        @Override
 272.210 +        public void exportField(Appendable out,
 272.211 +                                String destObject,
 272.212 +                                String mangledName,
 272.213 +                                FieldData fieldData) throws IOException {
 272.214 +        }
 272.215 +
 272.216 +        @Override
 272.217 +        public Collection<String> getExterns() {
 272.218 +            return Collections.EMPTY_LIST;
 272.219 +        }
 272.220 +    }
 272.221 +
 272.222 +    private static abstract class AdvancedObfuscationDelegate
 272.223 +            extends ClosuresObfuscationDelegate {
 272.224 +        private static final String[] INITIAL_EXTERNS = {
 272.225 +            "bck2brwsr",
 272.226 +            "$class",
 272.227 +            "anno",
 272.228 +            "array",
 272.229 +            "access",
 272.230 +            "cls",
 272.231 +            "vm",
 272.232 +            "loadClass",
 272.233 +            "loadBytes",
 272.234 +            "jvmName",
 272.235 +            "primitive",
 272.236 +            "superclass",
 272.237 +            "cnstr",
 272.238 +            "add32",
 272.239 +            "sub32",
 272.240 +            "mul32",
 272.241 +            "neg32",
 272.242 +            "toInt8",
 272.243 +            "toInt16",
 272.244 +            "next32",
 272.245 +            "high32",
 272.246 +            "toInt32",
 272.247 +            "toFP",
 272.248 +            "toLong",
 272.249 +            "toExactString",
 272.250 +            "add64",
 272.251 +            "sub64",
 272.252 +            "mul64",
 272.253 +            "and64",
 272.254 +            "or64",
 272.255 +            "xor64",
 272.256 +            "shl64",
 272.257 +            "shr64",
 272.258 +            "ushr64",
 272.259 +            "compare64",
 272.260 +            "neg64",
 272.261 +            "div32",
 272.262 +            "mod32",
 272.263 +            "div64",
 272.264 +            "mod64",
 272.265 +            "at",
 272.266 +            "getClass__Ljava_lang_Class_2",
 272.267 +            "clone__Ljava_lang_Object_2"
 272.268 +        };
 272.269 +
 272.270 +        private final Collection<String> externs;
 272.271 +
 272.272 +        protected AdvancedObfuscationDelegate() {
 272.273 +            externs = new ArrayList<String>(Arrays.asList(INITIAL_EXTERNS));
 272.274 +        }
 272.275 +
 272.276 +        @Override
 272.277 +        public void exportClass(Appendable out,
 272.278 +                                String destObject,
 272.279 +                                String mangledName,
 272.280 +                                ClassData classData) throws IOException {
 272.281 +            exportJSProperty(out, destObject, mangledName);
 272.282 +        }
 272.283 +
 272.284 +        @Override
 272.285 +        public void exportMethod(Appendable out,
 272.286 +                                 String destObject,
 272.287 +                                 String mangledName,
 272.288 +                                 MethodData methodData) throws IOException {
 272.289 +            if ((methodData.access & ByteCodeParser.ACC_PRIVATE) == 0) {
 272.290 +                exportJSProperty(out, destObject, mangledName);
 272.291 +            }
 272.292 +        }
 272.293 +
 272.294 +        @Override
 272.295 +        public void exportField(Appendable out,
 272.296 +                                String destObject,
 272.297 +                                String mangledName,
 272.298 +                                FieldData fieldData) throws IOException {
 272.299 +            if ((fieldData.access & ByteCodeParser.ACC_PRIVATE) == 0) {
 272.300 +                exportJSProperty(out, destObject, mangledName);
 272.301 +            }
 272.302 +        }
 272.303 +
 272.304 +        @Override
 272.305 +        public Collection<String> getExterns() {
 272.306 +            return externs;
 272.307 +        }
 272.308 +
 272.309 +        protected void addExtern(String extern) {
 272.310 +            externs.add(extern);
 272.311 +        }
 272.312 +    }
 272.313 +
 272.314 +    private static final class MediumObfuscationDelegate
 272.315 +            extends AdvancedObfuscationDelegate {
 272.316 +        @Override
 272.317 +        public void exportJSProperty(Appendable out,
 272.318 +                                     String destObject,
 272.319 +                                     String propertyName) {
 272.320 +            addExtern(propertyName);
 272.321 +        }
 272.322 +    }
 272.323 +
 272.324 +    private static final class FullObfuscationDelegate
 272.325 +            extends AdvancedObfuscationDelegate {
 272.326 +        @Override
 272.327 +        public void exportJSProperty(Appendable out,
 272.328 +                                     String destObject,
 272.329 +                                     String propertyName) throws IOException {
 272.330 +            out.append("\n").append(destObject).append("['")
 272.331 +                                               .append(propertyName)
 272.332 +                                               .append("'] = ")
 272.333 +                            .append(destObject).append(".").append(propertyName)
 272.334 +               .append(";\n");
 272.335 +        }
 272.336 +    }
 272.337 +}
   273.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   273.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/LdrRsrcs.java	Mon Oct 07 14:20:58 2013 +0200
   273.3 @@ -0,0 +1,48 @@
   273.4 +/**
   273.5 + * Back 2 Browser Bytecode Translator
   273.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   273.7 + *
   273.8 + * This program is free software: you can redistribute it and/or modify
   273.9 + * it under the terms of the GNU General Public License as published by
  273.10 + * the Free Software Foundation, version 2 of the License.
  273.11 + *
  273.12 + * This program is distributed in the hope that it will be useful,
  273.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  273.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  273.15 + * GNU General Public License for more details.
  273.16 + *
  273.17 + * You should have received a copy of the GNU General Public License
  273.18 + * along with this program. Look for COPYING file in the top folder.
  273.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  273.20 + */
  273.21 +package org.apidesign.vm4brwsr;
  273.22 +
  273.23 +import java.io.IOException;
  273.24 +import java.io.InputStream;
  273.25 +import java.net.URL;
  273.26 +import java.util.Enumeration;
  273.27 +
  273.28 +/** Implementation of Resources that delegates to some class loader.
  273.29 + *
  273.30 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  273.31 + */
  273.32 +final class LdrRsrcs implements Bck2Brwsr.Resources {
  273.33 +    private final ClassLoader loader;
  273.34 +
  273.35 +    LdrRsrcs(ClassLoader loader) {
  273.36 +        this.loader = loader;
  273.37 +    }
  273.38 +
  273.39 +    @Override
  273.40 +    public InputStream get(String name) throws IOException {
  273.41 +        Enumeration<URL> en = loader.getResources(name);
  273.42 +        URL u = null;
  273.43 +        while (en.hasMoreElements()) {
  273.44 +            u = en.nextElement();
  273.45 +        }
  273.46 +        if (u == null) {
  273.47 +            throw new IOException("Can't find " + name);
  273.48 +        }
  273.49 +        return u.openStream();
  273.50 +    }
  273.51 +}
   274.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java	Wed Feb 27 17:50:47 2013 +0100
   274.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/LocalsMapper.java	Mon Oct 07 14:20:58 2013 +0200
   274.3 @@ -18,8 +18,7 @@
   274.4  package org.apidesign.vm4brwsr;
   274.5  
   274.6  import java.io.IOException;
   274.7 -import org.apidesign.javap.RuntimeConstants;
   274.8 -import org.apidesign.javap.TypeArray;
   274.9 +import org.apidesign.vm4brwsr.ByteCodeParser.TypeArray;
  274.10  
  274.11  final class LocalsMapper {
  274.12      private final TypeArray argTypeRecords;
  274.13 @@ -113,7 +112,7 @@
  274.14          final int srcSize = stackMapTypes.getSize();
  274.15          for (int i = 0, dstIndex = 0; i < srcSize; ++i) {
  274.16              final int smType = stackMapTypes.get(i);
  274.17 -            if (smType == RuntimeConstants.ITEM_Bogus) {
  274.18 +            if (smType == ByteCodeParser.ITEM_Bogus) {
  274.19                  ++dstIndex;
  274.20                  continue;
  274.21              }
   275.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Wed Feb 27 17:50:47 2013 +0100
   275.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/Main.java	Mon Oct 07 14:20:58 2013 +0200
   275.3 @@ -18,6 +18,7 @@
   275.4  package org.apidesign.vm4brwsr;
   275.5  
   275.6  import java.io.BufferedWriter;
   275.7 +import java.io.File;
   275.8  import java.io.FileWriter;
   275.9  import java.io.IOException;
  275.10  import java.io.Writer;
  275.11 @@ -31,20 +32,69 @@
  275.12      private Main() {}
  275.13      
  275.14      public static void main(String... args) throws IOException {
  275.15 +        final String obfuscate = "--obfuscatelevel";
  275.16 +        
  275.17          if (args.length < 2) {
  275.18              System.err.println("Bck2Brwsr Translator from Java(tm) to JavaScript, (c) Jaroslav Tulach 2012");
  275.19 -            System.err.println("Usage: java -cp ... -jar ... <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
  275.20 -            return;
  275.21 +            System.err.println("Usage: java -cp ... -jar ... [");
  275.22 +            System.err.print(obfuscate);
  275.23 +            System.err.print(" [");
  275.24 +            boolean first = true;
  275.25 +            for (ObfuscationLevel l : ObfuscationLevel.values()) {
  275.26 +                if (!first) {
  275.27 +                    System.err.print('|');
  275.28 +                }
  275.29 +                System.err.print(l.name());
  275.30 +                first = false;
  275.31 +            }
  275.32 +                
  275.33 +            System.err.println("] <file_to_generate_js_code_to> java/lang/Class org/your/App ...");
  275.34 +            System.exit(9);
  275.35          }
  275.36          
  275.37 -        Writer w = new BufferedWriter(new FileWriter(args[0]));
  275.38 -        StringArray classes = StringArray.asList(args);
  275.39 -        classes.delete(0);
  275.40 -        try {
  275.41 -            Bck2Brwsr.generate(w, Main.class.getClassLoader(),
  275.42 -                               classes.toArray());
  275.43 -        } finally {
  275.44 -            w.close();
  275.45 +        ObfuscationLevel obfLevel = ObfuscationLevel.NONE;
  275.46 +        StringArray classes = new StringArray();
  275.47 +        String generateTo = null;
  275.48 +        for (int i = 0; i < args.length; i++) {
  275.49 +            if (obfuscate.equals(args[i])) { // NOI18N
  275.50 +                i++;
  275.51 +                try {
  275.52 +                    obfLevel = ObfuscationLevel.valueOf(args[i]);
  275.53 +                } catch (Exception e) {
  275.54 +                    System.err.print(obfuscate);
  275.55 +                    System.err.print(" parameter needs to be followed by one of ");
  275.56 +                    boolean first = true;
  275.57 +                    for (ObfuscationLevel l : ObfuscationLevel.values()) {
  275.58 +                        if (!first) {
  275.59 +                            System.err.print(", ");
  275.60 +                        }
  275.61 +                        System.err.print(l.name());
  275.62 +                        first = false;
  275.63 +                    }
  275.64 +                    System.err.println();
  275.65 +                    System.exit(1);
  275.66 +                }
  275.67 +                continue;
  275.68 +            }
  275.69 +            if (generateTo == null) {
  275.70 +                generateTo = args[i];
  275.71 +            } else {
  275.72 +                classes = classes.addAndNew(args[i]);
  275.73 +            }
  275.74 +        }
  275.75 +        
  275.76 +        File gt = new File(generateTo);
  275.77 +        if (Boolean.getBoolean("skip.if.exists") && gt.isFile()) {
  275.78 +            System.err.println("Skipping as " + gt + " exists.");
  275.79 +            System.exit(0);
  275.80 +        }
  275.81 +        
  275.82 +        try (Writer w = new BufferedWriter(new FileWriter(gt))) {
  275.83 +            Bck2Brwsr.newCompiler().
  275.84 +                obfuscation(obfLevel).
  275.85 +                addRootClasses(classes.toArray()).
  275.86 +                resources(Main.class.getClassLoader()).
  275.87 +                generate(w);
  275.88          }
  275.89      }
  275.90  }
   276.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   276.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ObfuscationDelegate.java	Mon Oct 07 14:20:58 2013 +0200
   276.3 @@ -0,0 +1,75 @@
   276.4 +/**
   276.5 + * Back 2 Browser Bytecode Translator
   276.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   276.7 + *
   276.8 + * This program is free software: you can redistribute it and/or modify
   276.9 + * it under the terms of the GNU General Public License as published by
  276.10 + * the Free Software Foundation, version 2 of the License.
  276.11 + *
  276.12 + * This program is distributed in the hope that it will be useful,
  276.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  276.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  276.15 + * GNU General Public License for more details.
  276.16 + *
  276.17 + * You should have received a copy of the GNU General Public License
  276.18 + * along with this program. Look for COPYING file in the top folder.
  276.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  276.20 + */
  276.21 +package org.apidesign.vm4brwsr;
  276.22 +
  276.23 +import java.io.IOException;
  276.24 +import org.apidesign.vm4brwsr.ByteCodeParser.ClassData;
  276.25 +import org.apidesign.vm4brwsr.ByteCodeParser.FieldData;
  276.26 +import org.apidesign.vm4brwsr.ByteCodeParser.MethodData;
  276.27 +
  276.28 +abstract class ObfuscationDelegate {
  276.29 +    static ObfuscationDelegate NULL =
  276.30 +            new ObfuscationDelegate() {
  276.31 +                @Override
  276.32 +                public void exportJSProperty(Appendable out,
  276.33 +                                             String destObject,
  276.34 +                                             String propertyName)
  276.35 +                            throws IOException {
  276.36 +                }
  276.37 +
  276.38 +                @Override
  276.39 +                public void exportClass(Appendable out,
  276.40 +                                        String destObject,
  276.41 +                                        String mangledName,
  276.42 +                                        ClassData classData)
  276.43 +                                            throws IOException {
  276.44 +                }
  276.45 +
  276.46 +                @Override
  276.47 +                public void exportMethod(Appendable out,
  276.48 +                                         String destObject,
  276.49 +                                         String mangledName,
  276.50 +                                         MethodData methodData)
  276.51 +                                             throws IOException {
  276.52 +                }
  276.53 +
  276.54 +                @Override
  276.55 +                public void exportField(Appendable out,
  276.56 +                                        String destObject,
  276.57 +                                        String mangledName,
  276.58 +                                        FieldData fieldData)
  276.59 +                                            throws IOException {
  276.60 +                }
  276.61 +            };
  276.62 +
  276.63 +    public abstract void exportJSProperty(
  276.64 +            Appendable out, String destObject, String propertyName)
  276.65 +                throws IOException;
  276.66 +
  276.67 +    public abstract void exportClass(
  276.68 +            Appendable out, String destObject, String mangledName,
  276.69 +            ClassData classData) throws IOException;
  276.70 +
  276.71 +    public abstract void exportMethod(
  276.72 +            Appendable out, String destObject, String mangledName,
  276.73 +            MethodData methodData) throws IOException;
  276.74 +
  276.75 +    public abstract void exportField(
  276.76 +            Appendable out, String destObject, String mangledName,
  276.77 +            FieldData fieldData) throws IOException;
  276.78 +}
   277.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   277.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/ObfuscationLevel.java	Mon Oct 07 14:20:58 2013 +0200
   277.3 @@ -0,0 +1,41 @@
   277.4 +/**
   277.5 + * Back 2 Browser Bytecode Translator
   277.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   277.7 + *
   277.8 + * This program is free software: you can redistribute it and/or modify
   277.9 + * it under the terms of the GNU General Public License as published by
  277.10 + * the Free Software Foundation, version 2 of the License.
  277.11 + *
  277.12 + * This program is distributed in the hope that it will be useful,
  277.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  277.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  277.15 + * GNU General Public License for more details.
  277.16 + *
  277.17 + * You should have received a copy of the GNU General Public License
  277.18 + * along with this program. Look for COPYING file in the top folder.
  277.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  277.20 + */
  277.21 +package org.apidesign.vm4brwsr;
  277.22 +
  277.23 +/**
  277.24 + * Defines obfuscation level of produced JavaScript files.
  277.25 + *
  277.26 + * @since 0.5
  277.27 + */
  277.28 +public enum ObfuscationLevel {
  277.29 +    /** Generated JavaScript is (sort of) human readable. Useful for debugging.
  277.30 +     * Dynamic capabilities of the virtual machine work on all classes.
  277.31 +     */
  277.32 +    NONE,
  277.33 +    /** White spaces are removed. Names of external symbols remain unchanged.
  277.34 +     * Dynamic capabilities of the virtual machine work on all classes.
  277.35 +     */
  277.36 +    MINIMAL,
  277.37 +// temporarily commented out before merge. not well defined yet:
  277.38 +//    MEDIUM,
  277.39 +    /** Aggressive obfuscation of everything. Compact, unreadable "one-liner".
  277.40 +     * One cannot load classes dynamically. Useful mostly for static compilation
  277.41 +     * of self contained application.
  277.42 +     */
  277.43 +    FULL
  277.44 +}
   278.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java	Wed Feb 27 17:50:47 2013 +0100
   278.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StackMapper.java	Mon Oct 07 14:20:58 2013 +0200
   278.3 @@ -17,7 +17,7 @@
   278.4   */
   278.5  package org.apidesign.vm4brwsr;
   278.6  
   278.7 -import org.apidesign.javap.TypeArray;
   278.8 +import org.apidesign.vm4brwsr.ByteCodeParser.TypeArray;
   278.9  
  278.10  final class StackMapper {
  278.11      private final TypeArray stackTypeIndexPairs;
   279.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java	Wed Feb 27 17:50:47 2013 +0100
   279.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/StringArray.java	Mon Oct 07 14:20:58 2013 +0200
   279.3 @@ -43,6 +43,25 @@
   279.4          }
   279.5          arr[arr.length - 1] = s;
   279.6      }
   279.7 +
   279.8 +    StringArray addAndNew(String... values) {
   279.9 +        int j;
  279.10 +        String[] tmp;
  279.11 +        if (arr == null) {
  279.12 +            tmp = new String[values.length];
  279.13 +            j = 0;
  279.14 +        } else {
  279.15 +            tmp = new String[arr.length + values.length];
  279.16 +            for (int i = 0; i < arr.length; i++) {
  279.17 +                tmp[i] = arr[i];
  279.18 +            }
  279.19 +            j = arr.length;
  279.20 +        }
  279.21 +        for (int i = 0; i < values.length;) {
  279.22 +            tmp[j++] = values[i++];
  279.23 +        }
  279.24 +        return new StringArray(tmp);
  279.25 +    }
  279.26      
  279.27      public String[] toArray() {
  279.28          return arr == null ? new String[0] : arr;
  279.29 @@ -93,5 +112,4 @@
  279.30          }
  279.31          return -1;
  279.32      }
  279.33 -    
  279.34  }
   280.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Wed Feb 27 17:50:47 2013 +0100
   280.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VM.java	Mon Oct 07 14:20:58 2013 +0200
   280.3 @@ -28,7 +28,11 @@
   280.4      public VM(Appendable out) {
   280.5          super(out);
   280.6      }
   280.7 -    
   280.8 +
   280.9 +    private VM(Appendable out, ObfuscationDelegate obfuscationDelegate) {
  280.10 +        super(out, obfuscationDelegate);
  280.11 +    }
  280.12 +
  280.13      static {
  280.14          // uses VMLazy to load dynamic classes
  280.15          boolean assertsOn = false;
  280.16 @@ -47,6 +51,12 @@
  280.17      static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names) throws IOException {
  280.18          new VM(out).doCompile(l, names);
  280.19      }
  280.20 +
  280.21 +    static void compile(Bck2Brwsr.Resources l, Appendable out, StringArray names,
  280.22 +                        ObfuscationDelegate obfuscationDelegate) throws IOException {
  280.23 +        new VM(out, obfuscationDelegate).doCompile(l, names);
  280.24 +    }
  280.25 +
  280.26      protected void doCompile(Bck2Brwsr.Resources l, StringArray names) throws IOException {
  280.27          out.append("(function VM(global) {var fillInVMSkeleton = function(vm) {");
  280.28          StringArray processed = new StringArray();
  280.29 @@ -110,7 +120,10 @@
  280.30              for (String ic : toInit.toArray()) {
  280.31                  int indx = processed.indexOf(ic);
  280.32                  if (indx >= 0) {
  280.33 -                    out.append(initCode.toArray()[indx]).append("\n");
  280.34 +                    final String theCode = initCode.toArray()[indx];
  280.35 +                    if (!theCode.isEmpty()) {
  280.36 +                        out.append(theCode).append("\n");
  280.37 +                    }
  280.38                      initCode.toArray()[indx] = "";
  280.39                  }
  280.40              }
  280.41 @@ -227,4 +240,9 @@
  280.42      String accessClass(String className) {
  280.43          return "vm." + className;
  280.44      }
  280.45 +
  280.46 +    @Override
  280.47 +    String getVMObject() {
  280.48 +        return "vm";
  280.49 +    }
  280.50  }
   281.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Wed Feb 27 17:50:47 2013 +0100
   281.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VMLazy.java	Mon Oct 07 14:20:58 2013 +0200
   281.3 @@ -56,7 +56,7 @@
   281.4              throw new ClassNotFoundException(name);
   281.5          }
   281.6  //        beingDefined(loader, name);
   281.7 -        StringBuilder out = new StringBuilder();
   281.8 +        StringBuilder out = new StringBuilder(65535);
   281.9          out.append("var loader = arguments[0];\n");
  281.10          out.append("var vm = loader.vm;\n");
  281.11          int prelude = out.length();
  281.12 @@ -130,6 +130,14 @@
  281.13  
  281.14          @Override
  281.15          protected void requireScript(String resourcePath) throws IOException {
  281.16 +            if (!resourcePath.startsWith("/")) {
  281.17 +                resourcePath = "/" + resourcePath;
  281.18 +            }
  281.19 +            String code = readCode(resourcePath);
  281.20 +            applyCode(lazy.loader, null, code, false);
  281.21 +        }
  281.22 +
  281.23 +        private String readCode(String resourcePath) throws IOException {
  281.24              InputStream is = getClass().getResourceAsStream(resourcePath);
  281.25              StringBuilder sb = new StringBuilder();
  281.26              for (;;) {
  281.27 @@ -139,7 +147,7 @@
  281.28                  }
  281.29                  sb.append((char)ch);
  281.30              }
  281.31 -            applyCode(lazy.loader, null, sb.toString(), false);
  281.32 +            return sb.toString();
  281.33          }
  281.34  
  281.35          @Override
  281.36 @@ -151,5 +159,10 @@
  281.37          String accessClass(String classOperation) {
  281.38              return "vm." + classOperation;
  281.39          }
  281.40 +
  281.41 +        @Override
  281.42 +        String getVMObject() {
  281.43 +            return "vm";
  281.44 +        }
  281.45      }
  281.46  }
   282.1 --- a/rt/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java	Wed Feb 27 17:50:47 2013 +0100
   282.2 +++ b/rt/vm/src/main/java/org/apidesign/vm4brwsr/VarType.java	Mon Oct 07 14:20:58 2013 +0200
   282.3 @@ -17,8 +17,6 @@
   282.4   */
   282.5  package org.apidesign.vm4brwsr;
   282.6  
   282.7 -import org.apidesign.javap.RuntimeConstants;
   282.8 -
   282.9  final class VarType {
  282.10      public static final int INTEGER = 0;
  282.11      public static final int LONG = 1;
  282.12 @@ -37,21 +35,21 @@
  282.13  
  282.14      public static int fromStackMapType(final int smType) {
  282.15          switch (smType & 0xff) {
  282.16 -            case RuntimeConstants.ITEM_Integer:
  282.17 +            case ByteCodeParser.ITEM_Integer:
  282.18                  return VarType.INTEGER;
  282.19 -            case RuntimeConstants.ITEM_Float:
  282.20 +            case ByteCodeParser.ITEM_Float:
  282.21                  return VarType.FLOAT;
  282.22 -            case RuntimeConstants.ITEM_Double:
  282.23 +            case ByteCodeParser.ITEM_Double:
  282.24                  return VarType.DOUBLE;
  282.25 -            case RuntimeConstants.ITEM_Long:
  282.26 +            case ByteCodeParser.ITEM_Long:
  282.27                  return VarType.LONG;
  282.28 -            case RuntimeConstants.ITEM_Null:
  282.29 -            case RuntimeConstants.ITEM_InitObject:
  282.30 -            case RuntimeConstants.ITEM_Object:
  282.31 -            case RuntimeConstants.ITEM_NewObject:
  282.32 +            case ByteCodeParser.ITEM_Null:
  282.33 +            case ByteCodeParser.ITEM_InitObject:
  282.34 +            case ByteCodeParser.ITEM_Object:
  282.35 +            case ByteCodeParser.ITEM_NewObject:
  282.36                  return VarType.REFERENCE;
  282.37  
  282.38 -            case RuntimeConstants.ITEM_Bogus:
  282.39 +            case ByteCodeParser.ITEM_Bogus:
  282.40                  /* unclear how to handle for now */
  282.41              default:
  282.42                  throw new IllegalStateException("Unhandled stack map type");
  282.43 @@ -60,25 +58,25 @@
  282.44  
  282.45      public static int fromConstantType(final byte constantTag) {
  282.46          switch (constantTag) {
  282.47 -            case RuntimeConstants.CONSTANT_INTEGER:
  282.48 +            case ByteCodeParser.CONSTANT_INTEGER:
  282.49                  return VarType.INTEGER;
  282.50 -            case RuntimeConstants.CONSTANT_FLOAT:
  282.51 +            case ByteCodeParser.CONSTANT_FLOAT:
  282.52                  return VarType.FLOAT;
  282.53 -            case RuntimeConstants.CONSTANT_LONG:
  282.54 +            case ByteCodeParser.CONSTANT_LONG:
  282.55                  return VarType.LONG;
  282.56 -            case RuntimeConstants.CONSTANT_DOUBLE:
  282.57 +            case ByteCodeParser.CONSTANT_DOUBLE:
  282.58                  return VarType.DOUBLE;
  282.59  
  282.60 -            case RuntimeConstants.CONSTANT_CLASS:
  282.61 -            case RuntimeConstants.CONSTANT_UTF8:
  282.62 -            case RuntimeConstants.CONSTANT_UNICODE:
  282.63 -            case RuntimeConstants.CONSTANT_STRING:
  282.64 +            case ByteCodeParser.CONSTANT_CLASS:
  282.65 +            case ByteCodeParser.CONSTANT_UTF8:
  282.66 +            case ByteCodeParser.CONSTANT_UNICODE:
  282.67 +            case ByteCodeParser.CONSTANT_STRING:
  282.68                  return VarType.REFERENCE;
  282.69  
  282.70 -            case RuntimeConstants.CONSTANT_FIELD:
  282.71 -            case RuntimeConstants.CONSTANT_METHOD:
  282.72 -            case RuntimeConstants.CONSTANT_INTERFACEMETHOD:
  282.73 -            case RuntimeConstants.CONSTANT_NAMEANDTYPE:
  282.74 +            case ByteCodeParser.CONSTANT_FIELD:
  282.75 +            case ByteCodeParser.CONSTANT_METHOD:
  282.76 +            case ByteCodeParser.CONSTANT_INTERFACEMETHOD:
  282.77 +            case ByteCodeParser.CONSTANT_NAMEANDTYPE:
  282.78                  /* unclear how to handle for now */
  282.79              default:
  282.80                  throw new IllegalStateException("Unhandled constant tag");
   283.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java	Wed Feb 27 17:50:47 2013 +0100
   283.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Array.java	Mon Oct 07 14:20:58 2013 +0200
   283.3 @@ -132,4 +132,8 @@
   283.4          arraycopy(arr()[0][0].chars, 0, arr, 0, 1);
   283.5          return arr[0];
   283.6      }
   283.7 +    
   283.8 +    public static int multiLen() {
   283.9 +        return new int[1][0].length;
  283.10 +    }
  283.11  }
   284.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Wed Feb 27 17:50:47 2013 +0100
   284.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ArrayTest.java	Mon Oct 07 14:20:58 2013 +0200
   284.3 @@ -18,6 +18,7 @@
   284.4  package org.apidesign.vm4brwsr;
   284.5  
   284.6  import static org.testng.Assert.*;
   284.7 +import org.testng.annotations.AfterClass;
   284.8  import org.testng.annotations.BeforeClass;
   284.9  import org.testng.annotations.Test;
  284.10  
  284.11 @@ -74,6 +75,9 @@
  284.12      @Test public void verifyInstanceOfArray() throws Exception {
  284.13          assertExec("Returns 'false'", Array.class, "instanceOfArray__ZLjava_lang_Object_2", Double.valueOf(0), "non-array");
  284.14      }
  284.15 +    @Test public void verifyMultiLen() throws Exception {
  284.16 +        assertExec("Multi len is one", Array.class, "multiLen__I", Double.valueOf(1));
  284.17 +    }
  284.18      
  284.19      private static TestVM code;
  284.20      
  284.21 @@ -81,6 +85,10 @@
  284.22      public void compileTheCode() throws Exception {
  284.23          code = TestVM.compileClass("org/apidesign/vm4brwsr/Array");
  284.24      }
  284.25 +    @AfterClass
  284.26 +    public static void releaseTheCode() {
  284.27 +        code = null;
  284.28 +    }
  284.29      private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
  284.30          code.assertExec(msg, clazz, method, expRes, args);
  284.31      }
   285.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Wed Feb 27 17:50:47 2013 +0100
   285.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ClassTest.java	Mon Oct 07 14:20:58 2013 +0200
   285.3 @@ -19,6 +19,7 @@
   285.4  
   285.5  import org.testng.annotations.Test;
   285.6  import static org.testng.Assert.*;
   285.7 +import org.testng.annotations.AfterClass;
   285.8  import org.testng.annotations.BeforeClass;
   285.9  
  285.10  /**
  285.11 @@ -190,6 +191,10 @@
  285.12      public void compileTheCode() throws Exception {
  285.13          code = TestVM.compileClass("org/apidesign/vm4brwsr/Classes");
  285.14      }
  285.15 +    @AfterClass
  285.16 +    public static void releaseTheCode() {
  285.17 +        code = null;
  285.18 +    }
  285.19      
  285.20      private void assertExec(
  285.21          String msg, Class clazz, String method, Object expRes, Object... args
  285.22 @@ -203,4 +208,24 @@
  285.23          );
  285.24      }
  285.25      
  285.26 +    @Test public void valueOfEnum() throws Exception {
  285.27 +        assertExec("can get value of enum", Classes.class,
  285.28 +            "valueEnum__Ljava_lang_String_2Ljava_lang_String_2",
  285.29 +            "TWO", "TWO"
  285.30 +        );
  285.31 +    }
  285.32 +
  285.33 +    @Test public void typeOfFn() throws Exception {
  285.34 +        assertExec("Type of function is Object", Classes.class,
  285.35 +            "typeOfFn__Ljava_lang_String_2",
  285.36 +            "java.lang.Object"
  285.37 +        );
  285.38 +    }
  285.39 +    
  285.40 +    @Test public void instanceOfSuperInterface() throws Exception {
  285.41 +        assertExec("Is iof super interface", Classes.class,
  285.42 +            "instanceOfSuperInterface__Z",
  285.43 +            1.0
  285.44 +        );
  285.45 +    }
  285.46  }
   286.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Wed Feb 27 17:50:47 2013 +0100
   286.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Classes.java	Mon Oct 07 14:20:58 2013 +0200
   286.3 @@ -18,6 +18,7 @@
   286.4  package org.apidesign.vm4brwsr;
   286.5  
   286.6  import java.io.IOException;
   286.7 +import java.io.Serializable;
   286.8  import java.lang.annotation.Annotation;
   286.9  import java.lang.annotation.Retention;
  286.10  import java.lang.annotation.RetentionPolicy;
  286.11 @@ -230,4 +231,23 @@
  286.12          return Application.class.isAssignableFrom(MyApplication.class);
  286.13      }
  286.14      
  286.15 +    public static String valueEnum(String v) {
  286.16 +        return ClassesMarker.E.valueOf(v).toString();
  286.17 +    }
  286.18 +    
  286.19 +    public static String typeOfFn() {
  286.20 +        return fn().getClass().getName();
  286.21 +    }
  286.22 +    
  286.23 +    @JavaScriptBody(args = {  }, body = "return function() { alert('x'); };")
  286.24 +    private native static Object fn();
  286.25 +    
  286.26 +    public static boolean instanceOfSuperInterface() {
  286.27 +        Object obj = new SuperSerial() {
  286.28 +        };
  286.29 +        return obj instanceof Serializable;
  286.30 +    }
  286.31 +    
  286.32 +    private static interface SuperSerial extends Serializable {
  286.33 +    }
  286.34  }
   287.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java	Wed Feb 27 17:50:47 2013 +0100
   287.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/ExceptionsTest.java	Mon Oct 07 14:20:58 2013 +0200
   287.3 @@ -19,6 +19,7 @@
   287.4  
   287.5  import javax.script.ScriptException;
   287.6  import static org.testng.Assert.*;
   287.7 +import org.testng.annotations.AfterClass;
   287.8  import org.testng.annotations.BeforeClass;
   287.9  import org.testng.annotations.Test;
  287.10  
  287.11 @@ -108,6 +109,10 @@
  287.12      public void compileTheCode() throws Exception {
  287.13          code = TestVM.compileClass("org/apidesign/vm4brwsr/Exceptions");
  287.14      }
  287.15 +    @AfterClass
  287.16 +    public static void releaseTheCode() {
  287.17 +        code = null;
  287.18 +    }
  287.19      private static void assertExec(String msg, Class clazz, String method, Object expRes, Object... args) throws Exception {
  287.20          code.assertExec(msg, clazz, method, expRes, args);
  287.21      }
   288.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Wed Feb 27 17:50:47 2013 +0100
   288.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/InstanceTest.java	Mon Oct 07 14:20:58 2013 +0200
   288.3 @@ -17,6 +17,7 @@
   288.4   */
   288.5  package org.apidesign.vm4brwsr;
   288.6  
   288.7 +import org.testng.annotations.AfterClass;
   288.8  import org.testng.annotations.Test;
   288.9  import org.testng.annotations.BeforeClass;
  288.10  
  288.11 @@ -156,6 +157,10 @@
  288.12      public void compileTheCode() throws Exception {
  288.13          code = TestVM.compileClass(startCompilationWith());
  288.14      }
  288.15 +    @AfterClass
  288.16 +    public static void releaseTheCode() {
  288.17 +        code = null;
  288.18 +    }
  288.19      
  288.20      private void assertExec(
  288.21          String msg, Class clazz, String method, Object expRes, Object... args
   289.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Wed Feb 27 17:50:47 2013 +0100
   289.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/NumberTest.java	Mon Oct 07 14:20:58 2013 +0200
   289.3 @@ -18,6 +18,7 @@
   289.4  package org.apidesign.vm4brwsr;
   289.5  
   289.6  import static org.testng.Assert.*;
   289.7 +import org.testng.annotations.AfterClass;
   289.8  import org.testng.annotations.BeforeClass;
   289.9  import org.testng.annotations.Test;
  289.10  
  289.11 @@ -184,13 +185,36 @@
  289.12              Double.valueOf(Long.MAX_VALUE / 5), 9
  289.13          );
  289.14      }
  289.15 +    @Test public void valueOfLongCharA() throws Exception {
  289.16 +        assertExec("Can we call JavaScripts valueOf on Character?", 
  289.17 +            Numbers.class, "seven__DI", 
  289.18 +            Double.valueOf('A'), 65
  289.19 +        );
  289.20 +    }
  289.21 +
  289.22 +    @Test public void valueOfLongBooleanTrue() throws Exception {
  289.23 +        assertExec("Can we call JavaScripts valueOf on Boolean?", 
  289.24 +            Numbers.class, "bseven__ZI", 
  289.25 +            true, 31
  289.26 +        );
  289.27 +    }
  289.28 +    @Test public void valueOfLongBooleanFalse() throws Exception {
  289.29 +        assertExec("Can we call JavaScripts valueOf on Boolean?", 
  289.30 +            Numbers.class, "bseven__ZI", 
  289.31 +            false, 30
  289.32 +        );
  289.33 +    }
  289.34  
  289.35      private static TestVM code;
  289.36  
  289.37      @BeforeClass
  289.38 -    public void compileTheCode() throws Exception {
  289.39 +    public static void compileTheCode() throws Exception {
  289.40          code = TestVM.compileClass("org/apidesign/vm4brwsr/Numbers");
  289.41      }
  289.42 +    @AfterClass
  289.43 +    public static void releaseTheCode() {
  289.44 +        code = null;
  289.45 +    }
  289.46  
  289.47      private static void assertExec(
  289.48          String msg, Class<?> clazz, String method, Object expRes, Object... args) throws Exception
   290.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Wed Feb 27 17:50:47 2013 +0100
   290.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/Numbers.java	Mon Oct 07 14:20:58 2013 +0200
   290.3 @@ -78,13 +78,26 @@
   290.4              case 4: return sevenNew().byteValue();
   290.5              case 8: return valueOf(Double.valueOf(7.0));
   290.6              case 9: return valueOf(Long.valueOf(Long.MAX_VALUE / 5));
   290.7 +            case 30: return valueOf(Boolean.FALSE);
   290.8 +            case 31: return valueOf(Boolean.TRUE);
   290.9 +            case 65: return valueOf(Character.valueOf('A'));
  290.10 +            default: throw new IllegalStateException();
  290.11 +        }
  290.12 +    }
  290.13 +    static boolean bseven(int todo) {
  290.14 +        switch (todo) {
  290.15 +            case 30: return bvalueOf(Boolean.FALSE);
  290.16 +            case 31: return bvalueOf(Boolean.TRUE);
  290.17              default: throw new IllegalStateException();
  290.18          }
  290.19      }
  290.20      
  290.21      @JavaScriptBody(args = {}, body = "return 7;")
  290.22      private static native Number sevenNew();
  290.23 +
  290.24 +    @JavaScriptBody(args = { "o" }, body = "return o.valueOf();")
  290.25 +    private static native double valueOf(Object o);
  290.26      
  290.27      @JavaScriptBody(args = { "o" }, body = "return o.valueOf();")
  290.28 -    private static native double valueOf(Object o);
  290.29 +    private static native boolean bvalueOf(Object o);
  290.30  }
   291.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Wed Feb 27 17:50:47 2013 +0100
   291.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticMethodTest.java	Mon Oct 07 14:20:58 2013 +0200
   291.3 @@ -18,6 +18,7 @@
   291.4  package org.apidesign.vm4brwsr;
   291.5  
   291.6  import static org.testng.Assert.*;
   291.7 +import org.testng.annotations.AfterClass;
   291.8  import org.testng.annotations.BeforeClass;
   291.9  import org.testng.annotations.Test;
  291.10  
  291.11 @@ -324,10 +325,14 @@
  291.12      private static TestVM code;
  291.13      
  291.14      @BeforeClass 
  291.15 -    public void compileTheCode() throws Exception {
  291.16 +    public static void compileTheCode() throws Exception {
  291.17          StringBuilder sb = new StringBuilder();
  291.18          code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticMethod");
  291.19      }
  291.20 +    @AfterClass
  291.21 +    public static void releaseTheCode() {
  291.22 +        code = null;
  291.23 +    }
  291.24  
  291.25      private void assertExec(
  291.26          String msg, Class<?> clazz, String method, 
   292.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   292.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticUseSub.java	Mon Oct 07 14:20:58 2013 +0200
   292.3 @@ -0,0 +1,24 @@
   292.4 +/**
   292.5 + * Back 2 Browser Bytecode Translator
   292.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   292.7 + *
   292.8 + * This program is free software: you can redistribute it and/or modify
   292.9 + * it under the terms of the GNU General Public License as published by
  292.10 + * the Free Software Foundation, version 2 of the License.
  292.11 + *
  292.12 + * This program is distributed in the hope that it will be useful,
  292.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  292.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  292.15 + * GNU General Public License for more details.
  292.16 + *
  292.17 + * You should have received a copy of the GNU General Public License
  292.18 + * along with this program. Look for COPYING file in the top folder.
  292.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  292.20 + */
  292.21 +package org.apidesign.vm4brwsr;
  292.22 +
  292.23 +public class StaticUseSub extends StaticUse {
  292.24 +    public static String getNonNull() {
  292.25 +        return NON_NULL.getClass().getName();
  292.26 +    }
  292.27 +}
   293.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
   293.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StaticUseSubTest.java	Mon Oct 07 14:20:58 2013 +0200
   293.3 @@ -0,0 +1,48 @@
   293.4 +/**
   293.5 + * Back 2 Browser Bytecode Translator
   293.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   293.7 + *
   293.8 + * This program is free software: you can redistribute it and/or modify
   293.9 + * it under the terms of the GNU General Public License as published by
  293.10 + * the Free Software Foundation, version 2 of the License.
  293.11 + *
  293.12 + * This program is distributed in the hope that it will be useful,
  293.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
  293.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  293.15 + * GNU General Public License for more details.
  293.16 + *
  293.17 + * You should have received a copy of the GNU General Public License
  293.18 + * along with this program. Look for COPYING file in the top folder.
  293.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
  293.20 + */
  293.21 +package org.apidesign.vm4brwsr;
  293.22 +
  293.23 +import org.testng.annotations.AfterClass;
  293.24 +import org.testng.annotations.BeforeClass;
  293.25 +import org.testng.annotations.Test;
  293.26 +
  293.27 +/**
  293.28 + *
  293.29 + * @author Jaroslav Tulach <jtulach@netbeans.org>
  293.30 + */
  293.31 +public class StaticUseSubTest {
  293.32 +    private static TestVM code;
  293.33 +
  293.34 +    @BeforeClass
  293.35 +    public static void compileTheCode() throws Exception {
  293.36 +        StringBuilder sb = new StringBuilder();
  293.37 +        code = TestVM.compileClass(sb, "org/apidesign/vm4brwsr/StaticUseSub");
  293.38 +    }
  293.39 +    @AfterClass
  293.40 +    public static void releaseTheCode() {
  293.41 +        code = null;
  293.42 +    }
  293.43 +    
  293.44 +    @Test public void getInheritedStaticField() throws Exception {
  293.45 +        code.assertExec(
  293.46 +            "Obtains non-null", StaticUseSub.class, 
  293.47 +            "getNonNull__Ljava_lang_String_2",
  293.48 +            "java.lang.Object"
  293.49 +        );
  293.50 +    }
  293.51 +}
   294.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java	Wed Feb 27 17:50:47 2013 +0100
   294.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringSample.java	Mon Oct 07 14:20:58 2013 +0200
   294.3 @@ -18,6 +18,7 @@
   294.4  package org.apidesign.vm4brwsr;
   294.5  
   294.6  import java.io.UnsupportedEncodingException;
   294.7 +import org.apidesign.bck2brwsr.core.JavaScriptBody;
   294.8  
   294.9  /**
  294.10   *
  294.11 @@ -129,4 +130,20 @@
  294.12      public String toString() {
  294.13          return HELLO + cnt;
  294.14      }
  294.15 +    
  294.16 +    @JavaScriptBody(args = {}, body = "return [1, 2];")
  294.17 +    private static native Object crtarr();
  294.18 +    @JavaScriptBody(args = { "o" }, body = "return o.toString();")
  294.19 +    private static native String toStrng(Object o);
  294.20 +    
  294.21 +    public static String toStringArray(boolean fakeArr, boolean toString) {
  294.22 +        final Object arr = fakeArr ? crtarr() : new Object[2];
  294.23 +        final String whole = toString ? arr.toString() : toStrng(arr);
  294.24 +        int zav = whole.indexOf('@');
  294.25 +        if (zav <= 0) {
  294.26 +            zav = whole.length();
  294.27 +        }
  294.28 +        return whole.substring(0, zav).toString().toString();
  294.29 +    }
  294.30 +    
  294.31  }
   295.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Wed Feb 27 17:50:47 2013 +0100
   295.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/StringTest.java	Mon Oct 07 14:20:58 2013 +0200
   295.3 @@ -19,6 +19,7 @@
   295.4  
   295.5  import org.testng.annotations.Test;
   295.6  import static org.testng.Assert.*;
   295.7 +import org.testng.annotations.AfterClass;
   295.8  import org.testng.annotations.BeforeClass;
   295.9  
  295.10  /**
  295.11 @@ -193,15 +194,47 @@
  295.12          
  295.13      }
  295.14      
  295.15 +    @Test public void toStringOnJSArray() throws Exception {
  295.16 +        String exp = StringSample.toStringArray(false, true);
  295.17 +        
  295.18 +        assertExec(
  295.19 +            "Treated as Java Object array",
  295.20 +            StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
  295.21 +            exp, true, true
  295.22 +        );
  295.23 +    }
  295.24 +
  295.25 +    @Test public void toStringOnRealArray() throws Exception {
  295.26 +        String exp = StringSample.toStringArray(false, true);
  295.27 +        
  295.28 +        assertExec(
  295.29 +            "Is Java Object array",
  295.30 +            StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
  295.31 +            exp, false, true
  295.32 +        );
  295.33 +    }
  295.34 +
  295.35 +    @Test public void valueOfOnJSArray() throws Exception {
  295.36 +        assertExec(
  295.37 +            "Treated as classical JavaScript array",
  295.38 +            StringSample.class, "toStringArray__Ljava_lang_String_2ZZ",
  295.39 +            "1,2", true, false
  295.40 +        );
  295.41 +    }
  295.42 +    
  295.43      private static TestVM code;
  295.44      
  295.45      @BeforeClass 
  295.46 -    public void compileTheCode() throws Exception {
  295.47 +    public static void compileTheCode() throws Exception {
  295.48          code = TestVM.compileClass(
  295.49              "org/apidesign/vm4brwsr/StringSample",
  295.50              "java/lang/String"
  295.51          );
  295.52      }
  295.53 +    @AfterClass
  295.54 +    public static void releaseTheCode() {
  295.55 +        code = null;
  295.56 +    }
  295.57      
  295.58      private static void assertExec(String msg, 
  295.59          Class<?> clazz, String method, Object expRes, Object... args
   296.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java	Wed Feb 27 17:50:47 2013 +0100
   296.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/SystemTest.java	Mon Oct 07 14:20:58 2013 +0200
   296.3 @@ -19,6 +19,7 @@
   296.4  
   296.5  import org.testng.annotations.BeforeClass;
   296.6  import static org.testng.Assert.*;
   296.7 +import org.testng.annotations.AfterClass;
   296.8  import org.testng.annotations.Test;
   296.9  
  296.10  /**
  296.11 @@ -51,6 +52,10 @@
  296.12          code = TestVM.compileClass(
  296.13              "org/apidesign/bck2brwsr/emul/lang/System");
  296.14      }
  296.15 +    @AfterClass
  296.16 +    public static void releaseTheCode() {
  296.17 +        code = null;
  296.18 +    }
  296.19      
  296.20  }
  296.21  
   297.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Wed Feb 27 17:50:47 2013 +0100
   297.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/TestVM.java	Mon Oct 07 14:20:58 2013 +0200
   297.3 @@ -51,7 +51,7 @@
   297.4              ret = code.invokeMethod(bck2brwsr, "loadClass", clazz.getName());
   297.5              ret = code.invokeMethod(ret, method, args);
   297.6          } catch (ScriptException ex) {
   297.7 -            fail("Execution failed in " + dumpJS(codeSeq), ex);
   297.8 +            fail("Execution failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
   297.9          } catch (NoSuchMethodException ex) {
  297.10              fail("Cannot find method in " + dumpJS(codeSeq), ex);
  297.11          }
  297.12 @@ -68,9 +68,9 @@
  297.13                  ret = code.invokeMethod(ret, "toFP");
  297.14                  ret = code.invokeFunction("Number", ret);
  297.15              } catch (ScriptException ex) {
  297.16 -                fail("Conversion to number failed in " + dumpJS(codeSeq), ex);
  297.17 +                fail("Conversion to number failed in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
  297.18              } catch (NoSuchMethodException ex) {
  297.19 -                fail("Cannot find global Number(x) function in " + dumpJS(codeSeq), ex);
  297.20 +                fail("Cannot find global Number(x) function in " + dumpJS(codeSeq) + ": " + ex.getMessage(), ex);
  297.21              }
  297.22          }
  297.23          return ret;
  297.24 @@ -115,7 +115,7 @@
  297.25              if (sb.length() > 2000) {
  297.26                  sb = dumpJS(sb);
  297.27              }
  297.28 -            fail("Could not evaluate:\n" + sb, ex);
  297.29 +            fail("Could not evaluate:" + ex.getClass() + ":" + ex.getMessage() + "\n" + sb, ex);
  297.30              return null;
  297.31          }
  297.32      }
   298.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Wed Feb 27 17:50:47 2013 +0100
   298.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMLazyTest.java	Mon Oct 07 14:20:58 2013 +0200
   298.3 @@ -22,6 +22,7 @@
   298.4  import javax.script.ScriptException;
   298.5  import org.testng.annotations.BeforeClass;
   298.6  import static org.testng.Assert.*;
   298.7 +import org.testng.annotations.AfterClass;
   298.8  import org.testng.annotations.Test;
   298.9  
  298.10  /** Implements loading class by class.
  298.11 @@ -32,7 +33,7 @@
  298.12      private static TestVM code;
  298.13  
  298.14      @BeforeClass
  298.15 -    public void compileTheCode() throws Exception {
  298.16 +    public static void compileTheCode() throws Exception {
  298.17          StringBuilder sb = new StringBuilder();
  298.18          sb.append("\nvar data = {};");
  298.19          sb.append("\nfunction test(clazz, method) {");
  298.20 @@ -51,6 +52,10 @@
  298.21          );
  298.22          arr[0].getContext().setAttribute("loader", new BytesLoader(), ScriptContext.ENGINE_SCOPE);
  298.23      }
  298.24 +    @AfterClass
  298.25 +    public static void releaseTheCode() {
  298.26 +        code = null;
  298.27 +    }
  298.28      
  298.29      @Test public void invokeStaticMethod() throws Exception {
  298.30          assertExec("Trying to get -1", "test", Double.valueOf(-1),
   299.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java	Wed Feb 27 17:50:47 2013 +0100
   299.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVM.java	Mon Oct 07 14:20:58 2013 +0200
   299.3 @@ -43,4 +43,9 @@
   299.4      @Override
   299.5      protected void requireScript(String resourcePath) {
   299.6      }
   299.7 +
   299.8 +    @Override
   299.9 +    String getVMObject() {
  299.10 +        return "global";
  299.11 +    }
  299.12  }
   300.1 --- a/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Wed Feb 27 17:50:47 2013 +0100
   300.2 +++ b/rt/vm/src/test/java/org/apidesign/vm4brwsr/VMinVMTest.java	Mon Oct 07 14:20:58 2013 +0200
   300.3 @@ -21,6 +21,7 @@
   300.4  import java.io.FileWriter;
   300.5  import java.io.IOException;
   300.6  import static org.testng.Assert.*;
   300.7 +import org.testng.annotations.AfterClass;
   300.8  import org.testng.annotations.BeforeClass;
   300.9  import org.testng.annotations.Test;
  300.10  
  300.11 @@ -39,12 +40,24 @@
  300.12          compareCode("org/apidesign/vm4brwsr/Classes.class");
  300.13      }
  300.14  
  300.15 +    @Test public void compareGeneratedCodeForToolkitClass() throws Exception {
  300.16 +        String genCode = compareCode("org/apidesign/vm4brwsr/Bck2BrwsrToolkit.class");
  300.17 +        int indx = genCode.indexOf("gt = 65604");
  300.18 +        if (indx >= 0) {
  300.19 +            fail("Goto to an invalid label:\n...." + genCode.substring(indx - 30, indx + 30) + "....");
  300.20 +        }
  300.21 +    }
  300.22 +
  300.23      @BeforeClass
  300.24 -    public void compileTheCode() throws Exception {
  300.25 +    public static void compileTheCode() throws Exception {
  300.26          code = TestVM.compileClass("org/apidesign/vm4brwsr/VMinVM");
  300.27      }
  300.28 +    @AfterClass
  300.29 +    public static void releaseTheCode() {
  300.30 +        code = null;
  300.31 +    }
  300.32      
  300.33 -    private void compareCode(final String nm) throws Exception, IOException {
  300.34 +    private String compareCode(final String nm) throws Exception, IOException {
  300.35          byte[] arr = BytesLoader.readClass(nm);
  300.36          String ret1 = VMinVM.toJavaScript(arr);
  300.37          
  300.38 @@ -83,5 +96,7 @@
  300.39              msg.append(code.toString());
  300.40              fail(msg.toString());
  300.41          }
  300.42 +        
  300.43 +        return ret1;
  300.44      }
  300.45  }
   301.1 Binary file rt/vm/src/test/resources/org/apidesign/vm4brwsr/Bck2BrwsrToolkit.class has changed
   302.1 --- a/rt/vmtest/pom.xml	Wed Feb 27 17:50:47 2013 +0100
   302.2 +++ b/rt/vmtest/pom.xml	Mon Oct 07 14:20:58 2013 +0200
   302.3 @@ -1,15 +1,14 @@
   302.4  <?xml version="1.0"?>
   302.5 -<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
   302.6 -    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   302.7 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   302.8    <modelVersion>4.0.0</modelVersion>
   302.9    <parent>
  302.10      <groupId>org.apidesign.bck2brwsr</groupId>
  302.11      <artifactId>rt</artifactId>
  302.12 -    <version>0.3-SNAPSHOT</version>
  302.13 +    <version>0.9-SNAPSHOT</version>
  302.14    </parent>
  302.15    <groupId>org.apidesign.bck2brwsr</groupId>
  302.16    <artifactId>vmtest</artifactId>
  302.17 -  <version>0.3-SNAPSHOT</version>
  302.18 +  <version>0.9-SNAPSHOT</version>
  302.19    
  302.20    <name>VM Testing APIs</name>
  302.21    <url>http://bck2brwsr.apidesign.org</url>
  302.22 @@ -24,6 +23,14 @@
  302.23                      <target>1.7</target>
  302.24                  </configuration>
  302.25              </plugin>
  302.26 +            <plugin>
  302.27 +                <groupId>org.apache.maven.plugins</groupId>
  302.28 +                <artifactId>maven-javadoc-plugin</artifactId>
  302.29 +                <configuration>
  302.30 +                    <excludePackageNames>org.apidesign.bck2brwsr.vmtest.impl</excludePackageNames>
  302.31 +                    <skip>false</skip>
  302.32 +                </configuration>
  302.33 +            </plugin>
  302.34          </plugins>
  302.35      </build>
  302.36      <properties>
  302.37 @@ -43,18 +50,6 @@
  302.38      </dependency>
  302.39      <dependency>
  302.40        <groupId>${project.groupId}</groupId>
  302.41 -      <artifactId>vm4brwsr</artifactId>
  302.42 -      <version>${project.version}</version>
  302.43 -      <type>jar</type>
  302.44 -    </dependency>
  302.45 -    <dependency>
  302.46 -      <groupId>${project.groupId}</groupId>
  302.47 -      <artifactId>emul.mini</artifactId>
  302.48 -      <version>${project.version}</version>
  302.49 -      <scope>test</scope>
  302.50 -    </dependency>
  302.51 -    <dependency>
  302.52 -      <groupId>${project.groupId}</groupId>
  302.53        <artifactId>launcher</artifactId>
  302.54        <version>${project.version}</version>
  302.55      </dependency>
   303.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java	Wed Feb 27 17:50:47 2013 +0100
   303.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/BrwsrTest.java	Mon Oct 07 14:20:58 2013 +0200
   303.3 @@ -29,6 +29,10 @@
   303.4   * The browser to is by default executed via {@link java.awt.Desktop#browse(java.net.URI)},
   303.5   * but one can change that by specifying <code>-Dvmtest.brwsrs=firefox,google-chrome</code>
   303.6   * property.
   303.7 + * <p>
   303.8 + * If the annotated method throws {@link InterruptedException}, it will return
   303.9 + * the processing to the browser and after 100ms, called again. This is useful
  303.10 + * for testing asynchronous communication, etc.
  303.11   *
  303.12   * @author Jaroslav Tulach <jtulach@netbeans.org>
  303.13   */
   304.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java	Wed Feb 27 17:50:47 2013 +0100
   304.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/Http.java	Mon Oct 07 14:20:58 2013 +0200
   304.3 @@ -23,8 +23,7 @@
   304.4  import java.lang.annotation.Target;
   304.5  
   304.6  /**
   304.7 - * Exposes HTTP page or pages to the running {@link BrwsrTest}, so it can access under
   304.8 - * the relative path.
   304.9 + * Exposes an {@link Resource HTTP page} or a set of {@link #value() pages} to the running {@link BrwsrTest}.
  304.10   *
  304.11   * @author Jaroslav Tulach <jtulach@netbeans.org>
  304.12   */
  304.13 @@ -34,8 +33,10 @@
  304.14      /** Set of pages to make available */
  304.15      public Resource[] value();
  304.16      
  304.17 -    /** Exposes an HTTP page to the running {@link BrwsrTest}, so it can access
  304.18 -     * under the relative path.
  304.19 +    /** Describes single HTTP page to the running {@link BrwsrTest}, so it can be 
  304.20 +     * accessed under the specified {@link #path() relative path}. The page
  304.21 +     * content can either be specified inline via {@link #content()} or as
  304.22 +     * an external {@link #resource() resource}.
  304.23       *
  304.24       * @author Jaroslav Tulach <jtulach@netbeans.org>
  304.25       */
  304.26 @@ -44,7 +45,7 @@
  304.27      public @interface Resource {
  304.28          /** path on the server that the test can use to access the exposed resource */
  304.29          String path();
  304.30 -        /** the content of the HttpResource */
  304.31 +        /** the content of the <code>Http.Resource</code> */
  304.32          String content();
  304.33          /** resource relative to the class that should be used instead of <code>content</code>.
  304.34           * Leave content equal to empty string.
  304.35 @@ -52,5 +53,10 @@
  304.36          String resource() default "";
  304.37          /** mime type of the resource */
  304.38          String mimeType();
  304.39 +        /** query parameters. Can be referenced from the {@link #content} as
  304.40 +         * <code>$0</code>, <code>$1</code>, etc. The values will be extracted
  304.41 +         * from URL parameters of the request.
  304.42 +         */
  304.43 +        String[] parameters() default {};
  304.44      }
  304.45  }
   305.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Wed Feb 27 17:50:47 2013 +0100
   305.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/VMTest.java	Mon Oct 07 14:20:58 2013 +0200
   305.3 @@ -17,27 +17,123 @@
   305.4   */
   305.5  package org.apidesign.bck2brwsr.vmtest;
   305.6  
   305.7 +import java.lang.annotation.Annotation;
   305.8 +import java.util.ArrayList;
   305.9 +import java.util.Arrays;
  305.10 +import java.util.List;
  305.11 +import org.apidesign.bck2brwsr.launcher.Launcher;
  305.12  import org.apidesign.bck2brwsr.vmtest.impl.CompareCase;
  305.13  import org.testng.annotations.Factory;
  305.14  
  305.15 -/** A TestNG {@link Factory} that seeks for {@link Compare} annotations
  305.16 - * in provided class and builds set of tests that compare the computations
  305.17 - * in real as well as JavaScript virtual machines. Use as:<pre>
  305.18 +/** A TestNG {@link Factory} that seeks for {@link Compare} and {@link BrwsrTest} annotations
  305.19 + * in provided class and builds set of tests that verify the functionality of <b>Bck2Brwsr</b> 
  305.20 + * based system. Use as:
  305.21 + * <pre>
  305.22   * {@code @}{@link Factory} public static create() {
  305.23 - *   return @{link VMTest}.{@link #create(YourClass.class);
  305.24 + *   return @{link VMTest}.{@link #create(java.lang.Class) create}(YourClass.class);
  305.25   * }</pre>
  305.26 - *
  305.27 + * where <code>YourClass</code> contains methods annotated with
  305.28 + * {@link Compare} and {@link BrwsrTest} annotations.
  305.29 + * 
  305.30   * @author Jaroslav Tulach <jtulach@netbeans.org>
  305.31   */
  305.32  public final class VMTest {
  305.33 -    /** Inspects <code>clazz</code> and for each {@lik Compare} method creates
  305.34 -     * instances of tests. Each instance runs the test in different virtual
  305.35 +    private final List<Class> classes = new ArrayList<>();
  305.36 +    private final List<String> launcher = new ArrayList<>();
  305.37 +    private Class<? extends Annotation> annotation = BrwsrTest.class;
  305.38 +    
  305.39 +    private VMTest() {
  305.40 +    }
  305.41 +    
  305.42 +    /** Inspects <code>clazz</code> and for each method annotated by
  305.43 +     * {@link Compare} or {@link BrwsrTest} creates
  305.44 +     * instances of tests. 
  305.45 +     * <p>
  305.46 +     * Each {@link Compare} instance runs the test in different virtual
  305.47       * machine and at the end they compare the results.
  305.48 +     * <p>
  305.49 +     * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started
  305.50 +     * browser}.
  305.51       * 
  305.52 -     * @param clazz the class to inspect
  305.53 +     * @param clazz the class (or classes) to inspect
  305.54       * @return the set of created tests
  305.55       */
  305.56 -    public static Object[] create(Class<?> clazz) {
  305.57 -        return CompareCase.create(clazz);
  305.58 +    public static Object[] create(Class clazz) {
  305.59 +        return newTests().withClasses(clazz).build();
  305.60 +    }
  305.61 +    
  305.62 +    /** Creates new builder for test execution. Continue with methods
  305.63 +     * like {@link #withClasses(java.lang.Class[])} or {@link #withLaunchers(java.lang.String[])}.
  305.64 +     * Finish the process by calling {@link #build()}.
  305.65 +     * 
  305.66 +     * @return new instance of a builder
  305.67 +     * @since 0.7
  305.68 +     */
  305.69 +    public static VMTest newTests() {
  305.70 +        return new VMTest();
  305.71 +    }
  305.72 +    
  305.73 +    /** Adds class (or classes) to the test execution. The classes are inspected
  305.74 +     * to contain methods annotated by
  305.75 +     * {@link Compare} or {@link BrwsrTest}. Appropriate set of TestNG test
  305.76 +     * cases is then created.
  305.77 +     * <p>
  305.78 +     * Each {@link Compare} instance runs the test in different virtual
  305.79 +     * machine and at the end they compare the results.
  305.80 +     * <p>
  305.81 +     * Each {@link BrwsrTest} annotated method is executed once in {@link Launcher started
  305.82 +     * browser}.
  305.83 +     * 
  305.84 +     * @param classes one or more classes to inspect
  305.85 +     * @since 0.7
  305.86 +     */
  305.87 +    public final VMTest withClasses(Class... classes) {
  305.88 +        this.classes.addAll(Arrays.asList(classes));
  305.89 +        return this;
  305.90 +    }
  305.91 +
  305.92 +    /** Adds list of launchers that should be used to execute tests defined
  305.93 +     * by {@link Compare} and {@link BrwsrTest} annotations. This value 
  305.94 +     * can be overrided by using <code>vmtest.brwsrs</code> property.
  305.95 +     * List of supported launchers is available in the documentation of
  305.96 +     * {@link Launcher}.
  305.97 +     * 
  305.98 +     * @param launcher names of one or more launchers to use for the execution
  305.99 +     *   of tests
 305.100 +     * @since 0.7
 305.101 +     */
 305.102 +    public final VMTest withLaunchers(String... launcher) {
 305.103 +        this.launcher.addAll(Arrays.asList(launcher));
 305.104 +        return this;
 305.105 +    }
 305.106 +
 305.107 +    /** Specifies which annotation annotates the test methods
 305.108 +     * to be executed. By 
 305.109 +     * default it is the {@link BrwsrTest} annotation. Methods in
 305.110 +     * {@link #withClasses(java.lang.Class[]) test classes} annotated by
 305.111 +     * this annotation will be executed.
 305.112 +     * 
 305.113 +     * @param aClass an annotation class 
 305.114 +     * @return this
 305.115 +     * @since 0.8
 305.116 +     */
 305.117 +    public final VMTest withTestAnnotation(Class<? extends Annotation> aClass) {
 305.118 +        if (!aClass.isAnnotation()) {
 305.119 +            throw new IllegalStateException();
 305.120 +        }
 305.121 +        this.annotation = aClass;
 305.122 +        return this;
 305.123 +    }
 305.124 +    
 305.125 +    /** Assembles the provided information into the final array of tests.
 305.126 +     * @return array of TestNG tests
 305.127 +     * @since 0.7
 305.128 +     */
 305.129 +    public final Object[] build() {
 305.130 +        return CompareCase.create(
 305.131 +            launcher.toArray(new String[0]), 
 305.132 +            classes.toArray(new Class[0]),
 305.133 +            annotation
 305.134 +        );
 305.135      }
 305.136  }
   306.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Wed Feb 27 17:50:47 2013 +0100
   306.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/Bck2BrwsrCase.java	Mon Oct 07 14:20:58 2013 +0200
   306.3 @@ -65,17 +65,17 @@
   306.4                  for (Http.Resource r : http) {
   306.5                      if (!r.content().isEmpty()) {
   306.6                          InputStream is = new ByteArrayInputStream(r.content().getBytes("UTF-8"));
   306.7 -                        c.addHttpResource(r.path(), r.mimeType(), is);
   306.8 +                        c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
   306.9                      } else {
  306.10                          InputStream is = m.getDeclaringClass().getResourceAsStream(r.resource());
  306.11 -                        c.addHttpResource(r.path(), r.mimeType(), is);
  306.12 +                        c.addHttpResource(r.path(), r.mimeType(), r.parameters(), is);
  306.13                      }
  306.14                  }
  306.15              }
  306.16              String res = c.invoke();
  306.17              value = res;
  306.18              if (fail) {
  306.19 -                int idx = res.indexOf(':');
  306.20 +                int idx = res == null ? -1 : res.indexOf(':');
  306.21                  if (idx >= 0) {
  306.22                      Class<? extends Throwable> thrwbl = null;
  306.23                      try {
   307.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Wed Feb 27 17:50:47 2013 +0100
   307.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/CompareCase.java	Mon Oct 07 14:20:58 2013 +0200
   307.3 @@ -17,6 +17,7 @@
   307.4   */
   307.5  package org.apidesign.bck2brwsr.vmtest.impl;
   307.6  
   307.7 +import java.lang.annotation.Annotation;
   307.8  import org.apidesign.bck2brwsr.vmtest.*;
   307.9  import java.lang.reflect.Method;
  307.10  import java.util.ArrayList;
  307.11 @@ -53,26 +54,25 @@
  307.12       * @param clazz the class to inspect
  307.13       * @return the set of created tests
  307.14       */
  307.15 -    public static Object[] create(Class<?> clazz) {
  307.16 -        Method[] arr = clazz.getMethods();
  307.17 +    public static Object[] create(String[] brwsr, Class[] classes, Class<? extends Annotation> brwsrTest) {
  307.18          List<Object> ret = new ArrayList<>();
  307.19          
  307.20          final LaunchSetup l = LaunchSetup.INSTANCE;
  307.21          ret.add(l);
  307.22          
  307.23 -        String[] brwsr;
  307.24          {
  307.25              String p = System.getProperty("vmtest.brwsrs");
  307.26              if (p != null) {
  307.27                  brwsr = p.split(",");
  307.28 -            } else {
  307.29 -                brwsr = new String[0];
  307.30              }
  307.31          }
  307.32          
  307.33 -        for (Method m : arr) {
  307.34 -            registerCompareCases(m, l, ret, brwsr);
  307.35 -            registerBrwsrCases(m, l, ret, brwsr);
  307.36 +        for (Class clazz : classes) {
  307.37 +            Method[] arr = clazz.getMethods();
  307.38 +            for (Method m : arr) {
  307.39 +                registerCompareCases(m, l, ret, brwsr);
  307.40 +                registerBrwsrCases(brwsrTest, m, l, ret, brwsr);
  307.41 +            }
  307.42          }
  307.43          return ret.toArray();
  307.44      }
  307.45 @@ -83,10 +83,34 @@
  307.46      @Test(dependsOnGroups = "run") public void compareResults() throws Throwable {
  307.47          Object v1 = first.value;
  307.48          Object v2 = second.value;
  307.49 -        if (v1 != null) {
  307.50 -            v1 = v1.toString();
  307.51 +        if (v1 instanceof Integer || v1 instanceof Long || v1 instanceof Byte || v1 instanceof Short) {
  307.52 +            try {
  307.53 +                v1 = Long.parseLong(v1.toString());
  307.54 +            } catch (NumberFormatException nfe) {
  307.55 +                v1 = "Can't parse " + v1.toString();
  307.56 +            }
  307.57 +            try {
  307.58 +                v2 = Long.parseLong(v2.toString());
  307.59 +            } catch (NumberFormatException nfe) {
  307.60 +                v2 = "Can't parse " + v2.toString();
  307.61 +            }
  307.62 +        } else if (v1 instanceof Number) {
  307.63 +            try {
  307.64 +                v1 = Double.parseDouble(v1.toString());
  307.65 +            } catch (NumberFormatException nfe) {
  307.66 +                v1 = "Can't parse " + v1.toString();
  307.67 +            }
  307.68 +            try {
  307.69 +                v2 = Double.parseDouble(v2.toString());
  307.70 +            } catch (NumberFormatException nfe) {
  307.71 +                v2 = "Can't parse " + v2.toString();
  307.72 +            }
  307.73          } else {
  307.74 -            v1 = "null";
  307.75 +            if (v1 != null) {
  307.76 +                v1 = v1.toString();
  307.77 +            } else {
  307.78 +                v1 = "null";
  307.79 +            }
  307.80          }
  307.81          try {
  307.82              Assert.assertEquals(v2, v1, "Comparing results");
  307.83 @@ -126,8 +150,8 @@
  307.84              ret.add(new CompareCase(m, real, cse));
  307.85          }
  307.86      }
  307.87 -    private static void registerBrwsrCases(Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
  307.88 -        BrwsrTest c = m.getAnnotation(BrwsrTest.class);
  307.89 +    private static void registerBrwsrCases(Class<? extends Annotation> brwsrTest, Method m, final LaunchSetup l, List<Object> ret, String[] brwsr) {
  307.90 +        Object c = m.getAnnotation(brwsrTest);
  307.91          if (c == null) {
  307.92              return;
  307.93          }
   308.1 --- a/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java	Wed Feb 27 17:50:47 2013 +0100
   308.2 +++ b/rt/vmtest/src/main/java/org/apidesign/bck2brwsr/vmtest/impl/LaunchSetup.java	Mon Oct 07 14:20:58 2013 +0200
   308.3 @@ -42,7 +42,14 @@
   308.4      } 
   308.5      private synchronized  Launcher js(boolean create) {
   308.6          if (js == null && create) {
   308.7 -            js = Launcher.createJavaScript();
   308.8 +            final String p = System.getProperty("vmtest.js", "script"); // NOI18N
   308.9 +            switch (p) {
  308.10 +                case "brwsr": js = Launcher.createBrowser(null); break; // NOI18N
  308.11 +                case "script": js = Launcher.createJavaScript(); break; // NOI18N
  308.12 +                default: throw new IllegalArgumentException(
  308.13 +                    "Unknown value of vmtest.js property: " + p
  308.14 +                );
  308.15 +            }
  308.16          }
  308.17          return js;
  308.18      } 
   309.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/AssertionTest.java	Wed Feb 27 17:50:47 2013 +0100
   309.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   309.3 @@ -1,43 +0,0 @@
   309.4 -/**
   309.5 - * Back 2 Browser Bytecode Translator
   309.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   309.7 - *
   309.8 - * This program is free software: you can redistribute it and/or modify
   309.9 - * it under the terms of the GNU General Public License as published by
  309.10 - * the Free Software Foundation, version 2 of the License.
  309.11 - *
  309.12 - * This program is distributed in the hope that it will be useful,
  309.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  309.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  309.15 - * GNU General Public License for more details.
  309.16 - *
  309.17 - * You should have received a copy of the GNU General Public License
  309.18 - * along with this program. Look for COPYING file in the top folder.
  309.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  309.20 - */
  309.21 -package org.apidesign.bck2brwsr.tck;
  309.22 -
  309.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  309.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  309.25 -import org.testng.annotations.Factory;
  309.26 -
  309.27 -/**
  309.28 - *
  309.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  309.30 - */
  309.31 -public class AssertionTest {
  309.32 -
  309.33 -    @Compare public Object checkAssert() throws ClassNotFoundException {
  309.34 -        try {
  309.35 -            assert false : "Is assertion status on?";
  309.36 -            return null;
  309.37 -        } catch (AssertionError ex) {
  309.38 -            return ex.getClass().getName();
  309.39 -        }
  309.40 -    }
  309.41 -    
  309.42 -    @Factory
  309.43 -    public static Object[] create() {
  309.44 -        return VMTest.create(AssertionTest.class);
  309.45 -    }
  309.46 -}
   310.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/BrwsrCheckTest.java	Wed Feb 27 17:50:47 2013 +0100
   310.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   310.3 @@ -1,57 +0,0 @@
   310.4 -/**
   310.5 - * Back 2 Browser Bytecode Translator
   310.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   310.7 - *
   310.8 - * This program is free software: you can redistribute it and/or modify
   310.9 - * it under the terms of the GNU General Public License as published by
  310.10 - * the Free Software Foundation, version 2 of the License.
  310.11 - *
  310.12 - * This program is distributed in the hope that it will be useful,
  310.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  310.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  310.15 - * GNU General Public License for more details.
  310.16 - *
  310.17 - * You should have received a copy of the GNU General Public License
  310.18 - * along with this program. Look for COPYING file in the top folder.
  310.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  310.20 - */
  310.21 -package org.apidesign.bck2brwsr.tck;
  310.22 -
  310.23 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  310.24 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  310.25 -import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
  310.26 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  310.27 -import org.testng.annotations.Factory;
  310.28 -
  310.29 -/**
  310.30 - *
  310.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  310.32 - */
  310.33 -public class BrwsrCheckTest {
  310.34 -
  310.35 -    @BrwsrTest public void assertWindowObjectIsDefined() {
  310.36 -        assert window() != null : "No window object found!";
  310.37 -    }
  310.38 -
  310.39 -    
  310.40 -    
  310.41 -    
  310.42 -    @HtmlFragment("<h1 id='hello'>\n"
  310.43 -        + "Hello!\n"
  310.44 -        + "</h1>\n")
  310.45 -    @BrwsrTest public void accessProvidedFragment() {
  310.46 -        assert getElementById("hello") != null : "Element with 'hello' ID found";
  310.47 -    }
  310.48 -    
  310.49 -    @Factory
  310.50 -    public static Object[] create() {
  310.51 -        return VMTest.create(BrwsrCheckTest.class);
  310.52 -    }
  310.53 -    
  310.54 -
  310.55 -    @JavaScriptBody(args = {}, body = "return window;")
  310.56 -    private static native Object window();
  310.57 -
  310.58 -    @JavaScriptBody(args = { "id" }, body = "return window.document.getElementById(id);")
  310.59 -    private static native Object getElementById(String id);
  310.60 -}
   311.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ByteArithmeticTest.java	Wed Feb 27 17:50:47 2013 +0100
   311.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   311.3 @@ -1,102 +0,0 @@
   311.4 -/**
   311.5 - * Back 2 Browser Bytecode Translator
   311.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   311.7 - *
   311.8 - * This program is free software: you can redistribute it and/or modify
   311.9 - * it under the terms of the GNU General Public License as published by
  311.10 - * the Free Software Foundation, version 2 of the License.
  311.11 - *
  311.12 - * This program is distributed in the hope that it will be useful,
  311.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  311.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  311.15 - * GNU General Public License for more details.
  311.16 - *
  311.17 - * You should have received a copy of the GNU General Public License
  311.18 - * along with this program. Look for COPYING file in the top folder.
  311.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  311.20 - */
  311.21 -package org.apidesign.bck2brwsr.tck;
  311.22 -
  311.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  311.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  311.25 -import org.testng.annotations.Factory;
  311.26 -
  311.27 -/**
  311.28 - *
  311.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  311.30 - */
  311.31 -public class ByteArithmeticTest {
  311.32 -    
  311.33 -    private static byte add(byte x, byte y) {
  311.34 -        return (byte)(x + y);
  311.35 -    }
  311.36 -    
  311.37 -    private static byte sub(byte x, byte y) {
  311.38 -        return (byte)(x - y);
  311.39 -    }
  311.40 -    
  311.41 -    private static byte mul(byte x, byte y) {
  311.42 -        return (byte)(x * y);
  311.43 -    }
  311.44 -    
  311.45 -    private static byte div(byte x, byte y) {
  311.46 -        return (byte)(x / y);
  311.47 -    }
  311.48 -    
  311.49 -    private static byte mod(byte x, byte y) {
  311.50 -        return (byte)(x % y);
  311.51 -    }
  311.52 -    
  311.53 -    @Compare public byte conversion() {
  311.54 -        return (byte)123456;
  311.55 -    }
  311.56 -    
  311.57 -    @Compare public byte addOverflow() {
  311.58 -        return add(Byte.MAX_VALUE, (byte)1);
  311.59 -    }
  311.60 -    
  311.61 -    @Compare public byte subUnderflow() {
  311.62 -        return sub(Byte.MIN_VALUE, (byte)1);
  311.63 -    }
  311.64 -    
  311.65 -    @Compare public byte addMaxByteAndMaxByte() {
  311.66 -        return add(Byte.MAX_VALUE, Byte.MAX_VALUE);
  311.67 -    }
  311.68 -    
  311.69 -    @Compare public byte subMinByteAndMinByte() {
  311.70 -        return sub(Byte.MIN_VALUE, Byte.MIN_VALUE);
  311.71 -    }
  311.72 -    
  311.73 -    @Compare public byte multiplyMaxByte() {
  311.74 -        return mul(Byte.MAX_VALUE, (byte)2);
  311.75 -    }
  311.76 -    
  311.77 -    @Compare public byte multiplyMaxByteAndMaxByte() {
  311.78 -        return mul(Byte.MAX_VALUE, Byte.MAX_VALUE);
  311.79 -    }
  311.80 -    
  311.81 -    @Compare public byte multiplyMinByte() {
  311.82 -        return mul(Byte.MIN_VALUE, (byte)2);
  311.83 -    }
  311.84 -    
  311.85 -    @Compare public byte multiplyMinByteAndMinByte() {
  311.86 -        return mul(Byte.MIN_VALUE, Byte.MIN_VALUE);
  311.87 -    }
  311.88 -    
  311.89 -    @Compare public byte multiplyPrecision() {
  311.90 -        return mul((byte)17638, (byte)1103);
  311.91 -    }
  311.92 -    
  311.93 -    @Compare public byte division() {
  311.94 -        return div((byte)1, (byte)2);
  311.95 -    }
  311.96 -    
  311.97 -    @Compare public byte divisionReminder() {
  311.98 -        return mod((byte)1, (byte)2);
  311.99 -    }
 311.100 -    
 311.101 -    @Factory
 311.102 -    public static Object[] create() {
 311.103 -        return VMTest.create(ByteArithmeticTest.class);
 311.104 -    }
 311.105 -}
   312.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CloneTest.java	Wed Feb 27 17:50:47 2013 +0100
   312.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   312.3 @@ -1,73 +0,0 @@
   312.4 -/**
   312.5 - * Back 2 Browser Bytecode Translator
   312.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   312.7 - *
   312.8 - * This program is free software: you can redistribute it and/or modify
   312.9 - * it under the terms of the GNU General Public License as published by
  312.10 - * the Free Software Foundation, version 2 of the License.
  312.11 - *
  312.12 - * This program is distributed in the hope that it will be useful,
  312.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  312.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  312.15 - * GNU General Public License for more details.
  312.16 - *
  312.17 - * You should have received a copy of the GNU General Public License
  312.18 - * along with this program. Look for COPYING file in the top folder.
  312.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  312.20 - */
  312.21 -package org.apidesign.bck2brwsr.tck;
  312.22 -
  312.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  312.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  312.25 -import org.testng.annotations.Factory;
  312.26 -
  312.27 -/**
  312.28 - *
  312.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  312.30 - */
  312.31 -public class CloneTest {
  312.32 -    private int value;
  312.33 -    
  312.34 -    @Compare
  312.35 -    public Object notSupported() throws CloneNotSupportedException {
  312.36 -        return this.clone();
  312.37 -    }
  312.38 -
  312.39 -    @Compare public String sameClass() throws CloneNotSupportedException {
  312.40 -        return new Clnbl().clone().getClass().getName();
  312.41 -    }
  312.42 -
  312.43 -    @Compare public boolean differentInstance() throws CloneNotSupportedException {
  312.44 -        Clnbl orig = new Clnbl();
  312.45 -        return orig == orig.clone();
  312.46 -    }
  312.47 -
  312.48 -    @Compare public int sameReference() throws CloneNotSupportedException {
  312.49 -        CloneTest self = this;
  312.50 -        Clnbl orig = new Clnbl();
  312.51 -        self.value = 33;
  312.52 -        orig.ref = self;
  312.53 -        return ((Clnbl)orig.clone()).ref.value;
  312.54 -    }
  312.55 -
  312.56 -    @Compare public int sameValue() throws CloneNotSupportedException {
  312.57 -        Clnbl orig = new Clnbl();
  312.58 -        orig.value = 10;
  312.59 -        return ((Clnbl)orig.clone()).value;
  312.60 -    }
  312.61 -    
  312.62 -    @Factory
  312.63 -    public static Object[] create() {
  312.64 -        return VMTest.create(CloneTest.class);
  312.65 -    }
  312.66 -    
  312.67 -    public static final class Clnbl implements Cloneable {
  312.68 -        public CloneTest ref;
  312.69 -        private int value;
  312.70 -
  312.71 -        @Override
  312.72 -        public Object clone() throws CloneNotSupportedException {
  312.73 -            return super.clone();
  312.74 -        }
  312.75 -    }
  312.76 -}
   313.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareByteArrayTest.java	Wed Feb 27 17:50:47 2013 +0100
   313.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   313.3 @@ -1,93 +0,0 @@
   313.4 -/**
   313.5 - * Back 2 Browser Bytecode Translator
   313.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   313.7 - *
   313.8 - * This program is free software: you can redistribute it and/or modify
   313.9 - * it under the terms of the GNU General Public License as published by
  313.10 - * the Free Software Foundation, version 2 of the License.
  313.11 - *
  313.12 - * This program is distributed in the hope that it will be useful,
  313.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  313.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  313.15 - * GNU General Public License for more details.
  313.16 - *
  313.17 - * You should have received a copy of the GNU General Public License
  313.18 - * along with this program. Look for COPYING file in the top folder.
  313.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  313.20 - */
  313.21 -package org.apidesign.bck2brwsr.tck;
  313.22 -
  313.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  313.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  313.25 -import org.testng.annotations.Factory;
  313.26 -
  313.27 -/**
  313.28 - *
  313.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  313.30 - */
  313.31 -public class CompareByteArrayTest {
  313.32 -    @Compare public int byteArraySum() {
  313.33 -        byte[] arr = createArray();
  313.34 -        return sumByteArr(arr);
  313.35 -    }
  313.36 -    
  313.37 -    @Compare public int countZeros() {
  313.38 -        int zeros = 0;
  313.39 -        for (Byte b : createArray()) {
  313.40 -            if (b == 0) {
  313.41 -                zeros++;
  313.42 -            }
  313.43 -        }
  313.44 -        return zeros;
  313.45 -    }
  313.46 -    
  313.47 -    private static int sumByteArr(byte[] arr) {
  313.48 -        int sum = 0;
  313.49 -        for (int i = 0; i < arr.length; i++) {
  313.50 -            sum += arr[i];
  313.51 -        }
  313.52 -        return sum;
  313.53 -    }
  313.54 -    
  313.55 -    @Compare public String noOutOfBounds() {
  313.56 -        return atIndex(1);
  313.57 -    }
  313.58 -
  313.59 -    @Compare public String outOfBounds() {
  313.60 -        return atIndex(5);
  313.61 -    }
  313.62 -
  313.63 -    @Compare public String outOfBoundsMinus() {
  313.64 -        return atIndex(-1);
  313.65 -    }
  313.66 -
  313.67 -    @Compare public String toOfBounds() {
  313.68 -        return toIndex(5);
  313.69 -    }
  313.70 -
  313.71 -    @Compare public String toOfBoundsMinus() {
  313.72 -        return toIndex(-1);
  313.73 -    }
  313.74 -
  313.75 -    private static final int[] arr = { 0, 1, 2 };
  313.76 -    public static String atIndex(int at) {
  313.77 -        return "at@" + arr[at];
  313.78 -    }
  313.79 -    public static String toIndex(int at) {
  313.80 -        arr[at] = 10;
  313.81 -        return "ok";
  313.82 -    }
  313.83 -    
  313.84 -    
  313.85 -    @Factory
  313.86 -    public static Object[] create() {
  313.87 -        return VMTest.create(CompareByteArrayTest.class);
  313.88 -    }
  313.89 -
  313.90 -    private byte[] createArray() {
  313.91 -        byte[] arr = new byte[10];
  313.92 -        arr[5] = 3;
  313.93 -        arr[7] = 8;
  313.94 -        return arr;
  313.95 -    }
  313.96 -}
   314.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareHashTest.java	Wed Feb 27 17:50:47 2013 +0100
   314.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   314.3 @@ -1,50 +0,0 @@
   314.4 -/**
   314.5 - * Back 2 Browser Bytecode Translator
   314.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   314.7 - *
   314.8 - * This program is free software: you can redistribute it and/or modify
   314.9 - * it under the terms of the GNU General Public License as published by
  314.10 - * the Free Software Foundation, version 2 of the License.
  314.11 - *
  314.12 - * This program is distributed in the hope that it will be useful,
  314.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  314.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  314.15 - * GNU General Public License for more details.
  314.16 - *
  314.17 - * You should have received a copy of the GNU General Public License
  314.18 - * along with this program. Look for COPYING file in the top folder.
  314.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  314.20 - */
  314.21 -package org.apidesign.bck2brwsr.tck;
  314.22 -
  314.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  314.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  314.25 -import org.testng.annotations.Factory;
  314.26 -
  314.27 -/**
  314.28 - *
  314.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  314.30 - */
  314.31 -public class CompareHashTest {
  314.32 -    @Compare public int hashOfString() {
  314.33 -        return "Ahoj".hashCode();
  314.34 -    }
  314.35 -    
  314.36 -    @Compare public int hashRemainsYieldsZero() {
  314.37 -        Object o = new Object();
  314.38 -        return o.hashCode() - o.hashCode();
  314.39 -    }
  314.40 -    
  314.41 -    @Compare public int initializeInStatic() {
  314.42 -        return StaticUse.NON_NULL.hashCode() - StaticUse.NON_NULL.hashCode();
  314.43 -    }
  314.44 -    
  314.45 -    @Compare public int hashOfInt() {
  314.46 -        return Integer.valueOf(Integer.MAX_VALUE).hashCode();
  314.47 -    }
  314.48 -    
  314.49 -    @Factory
  314.50 -    public static Object[] create() {
  314.51 -        return VMTest.create(CompareHashTest.class);
  314.52 -    }
  314.53 -}
   315.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareIntArrayTest.java	Wed Feb 27 17:50:47 2013 +0100
   315.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   315.3 @@ -1,63 +0,0 @@
   315.4 -/**
   315.5 - * Back 2 Browser Bytecode Translator
   315.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   315.7 - *
   315.8 - * This program is free software: you can redistribute it and/or modify
   315.9 - * it under the terms of the GNU General Public License as published by
  315.10 - * the Free Software Foundation, version 2 of the License.
  315.11 - *
  315.12 - * This program is distributed in the hope that it will be useful,
  315.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  315.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  315.15 - * GNU General Public License for more details.
  315.16 - *
  315.17 - * You should have received a copy of the GNU General Public License
  315.18 - * along with this program. Look for COPYING file in the top folder.
  315.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  315.20 - */
  315.21 -package org.apidesign.bck2brwsr.tck;
  315.22 -
  315.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  315.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  315.25 -import org.testng.annotations.Factory;
  315.26 -
  315.27 -/**
  315.28 - *
  315.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  315.30 - */
  315.31 -public class CompareIntArrayTest {
  315.32 -    @Compare public int integerArraySum() {
  315.33 -        int[] arr = createArray();
  315.34 -        return sumIntArr(arr);
  315.35 -    }
  315.36 -    
  315.37 -    @Compare public int countZeros() {
  315.38 -        int zeros = 0;
  315.39 -        for (Integer i : createArray()) {
  315.40 -            if (i == 0) {
  315.41 -                zeros++;
  315.42 -            }
  315.43 -        }
  315.44 -        return zeros;
  315.45 -    }
  315.46 -    
  315.47 -    private static int sumIntArr(int[] arr) {
  315.48 -        int sum = 0;
  315.49 -        for (int i = 0; i < arr.length; i++) {
  315.50 -            sum += arr[i];
  315.51 -        }
  315.52 -        return sum;
  315.53 -    }
  315.54 -    
  315.55 -    @Factory
  315.56 -    public static Object[] create() {
  315.57 -        return VMTest.create(CompareIntArrayTest.class);
  315.58 -    }
  315.59 -
  315.60 -    private int[] createArray() {
  315.61 -        int[] arr = new int[10];
  315.62 -        arr[5] = 3;
  315.63 -        arr[7] = 8;
  315.64 -        return arr;
  315.65 -    }
  315.66 -}
   316.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/CompareStringsTest.java	Wed Feb 27 17:50:47 2013 +0100
   316.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   316.3 @@ -1,162 +0,0 @@
   316.4 -/**
   316.5 - * Back 2 Browser Bytecode Translator
   316.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   316.7 - *
   316.8 - * This program is free software: you can redistribute it and/or modify
   316.9 - * it under the terms of the GNU General Public License as published by
  316.10 - * the Free Software Foundation, version 2 of the License.
  316.11 - *
  316.12 - * This program is distributed in the hope that it will be useful,
  316.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  316.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  316.15 - * GNU General Public License for more details.
  316.16 - *
  316.17 - * You should have received a copy of the GNU General Public License
  316.18 - * along with this program. Look for COPYING file in the top folder.
  316.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  316.20 - */
  316.21 -package org.apidesign.bck2brwsr.tck;
  316.22 -
  316.23 -import java.io.UnsupportedEncodingException;
  316.24 -import java.net.MalformedURLException;
  316.25 -import java.net.URL;
  316.26 -import org.apidesign.bck2brwsr.vmtest.Compare;
  316.27 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  316.28 -import org.testng.annotations.Factory;
  316.29 -
  316.30 -/**
  316.31 - *
  316.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  316.33 - */
  316.34 -public class CompareStringsTest {
  316.35 -    @Compare public String firstChar() {
  316.36 -        return "" + ("Hello".toCharArray()[0]);
  316.37 -    }
  316.38 -    
  316.39 -    @Compare public String classCast() {
  316.40 -        Object o = firstChar();
  316.41 -        return String.class.cast(o);
  316.42 -    }
  316.43 -
  316.44 -    @Compare public String classCastThrown() {
  316.45 -        Object o = null;
  316.46 -        return String.class.cast(o);
  316.47 -    }
  316.48 -    
  316.49 -    @Compare public boolean equalToNull() {
  316.50 -        return "Ahoj".equals(null);
  316.51 -    }
  316.52 -    
  316.53 -    @Compare public int highByteLenght() {
  316.54 -        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
  316.55 -        return new String(arr, 0).length();
  316.56 -    }
  316.57 -    
  316.58 -    @Compare public String highByte() {
  316.59 -        byte[] arr= { 77,97,110,105,102,101,115,116,45,86,101,114,115,105,111,110 };
  316.60 -        StringBuilder sb = new StringBuilder();
  316.61 -        sb.append("pref:");
  316.62 -        sb.append(new String(arr, 0));
  316.63 -        return sb.toString();
  316.64 -    }
  316.65 -    
  316.66 -    @Compare public static Object compareURLs() throws MalformedURLException {
  316.67 -        return new URL("http://apidesign.org:8080/wiki/").toExternalForm().toString();
  316.68 -    }
  316.69 -    
  316.70 -    @Compare public String deleteLastTwoCharacters() {
  316.71 -        StringBuilder sb = new StringBuilder();
  316.72 -        sb.append("453.0");
  316.73 -        if (sb.toString().endsWith(".0")) {
  316.74 -            final int l = sb.length();
  316.75 -            sb.delete(l - 2, l);
  316.76 -        }
  316.77 -        return sb.toString().toString();
  316.78 -    }
  316.79 -    
  316.80 -    @Compare public String nameOfStringClass() throws Exception {
  316.81 -        return Class.forName("java.lang.String").getName();
  316.82 -    }
  316.83 -    @Compare public String nameOfArrayClass() throws Exception {
  316.84 -        return Class.forName("org.apidesign.bck2brwsr.tck.CompareHashTest").getName();
  316.85 -    }
  316.86 -    
  316.87 -    @Compare public String lowerHello() {
  316.88 -        return "HeLlO".toLowerCase();
  316.89 -    }
  316.90 -    
  316.91 -    @Compare public String lowerA() {
  316.92 -        return String.valueOf(Character.toLowerCase('A')).toString();
  316.93 -    }
  316.94 -    @Compare public String upperHello() {
  316.95 -        return "hello".toUpperCase();
  316.96 -    }
  316.97 -    
  316.98 -    @Compare public String upperA() {
  316.99 -        return String.valueOf(Character.toUpperCase('a')).toString();
 316.100 -    }
 316.101 -    
 316.102 -    @Compare public boolean matchRegExp() throws Exception {
 316.103 -        return "58038503".matches("\\d*");
 316.104 -    }
 316.105 -
 316.106 -    @Compare public boolean doesNotMatchRegExp() throws Exception {
 316.107 -        return "58038503GH".matches("\\d*");
 316.108 -    }
 316.109 -
 316.110 -    @Compare public boolean doesNotMatchRegExpFully() throws Exception {
 316.111 -        return "Hello".matches("Hell");
 316.112 -    }
 316.113 -    
 316.114 -    @Compare public String emptyCharArray() {
 316.115 -        char[] arr = new char[10];
 316.116 -        return new String(arr);
 316.117 -    }
 316.118 -    
 316.119 -    @Compare public String variousCharacterTests() throws Exception {
 316.120 -        StringBuilder sb = new StringBuilder();
 316.121 -        
 316.122 -        sb.append(Character.isUpperCase('a'));
 316.123 -        sb.append(Character.isUpperCase('A'));
 316.124 -        sb.append(Character.isLowerCase('a'));
 316.125 -        sb.append(Character.isLowerCase('A'));
 316.126 -        
 316.127 -        sb.append(Character.isLetter('A'));
 316.128 -        sb.append(Character.isLetterOrDigit('9'));
 316.129 -        sb.append(Character.isLetterOrDigit('A'));
 316.130 -        sb.append(Character.isLetter('0'));
 316.131 -        
 316.132 -        return sb.toString().toString();
 316.133 -    }
 316.134 -        
 316.135 -    @Compare
 316.136 -    public String nullFieldInitialized() {
 316.137 -        NullField nf = new NullField();
 316.138 -        return ("" + nf.name).toString();
 316.139 -    }
 316.140 -    @Compare
 316.141 -    public String toUTFString() throws UnsupportedEncodingException {
 316.142 -        byte[] arr = {
 316.143 -            (byte) -59, (byte) -67, (byte) 108, (byte) 117, (byte) -59, (byte) -91,
 316.144 -            (byte) 111, (byte) 117, (byte) -60, (byte) -115, (byte) 107, (byte) -61,
 316.145 -            (byte) -67, (byte) 32, (byte) 107, (byte) -59, (byte) -81, (byte) -59,
 316.146 -            (byte) -120
 316.147 -        };
 316.148 -        return new String(arr, "utf-8");
 316.149 -    }
 316.150 -
 316.151 -    @Compare
 316.152 -    public int stringToBytesLenght() throws UnsupportedEncodingException {
 316.153 -        return "\u017dlu\u0165ou\u010dk\u00fd k\u016f\u0148".getBytes("utf8").length;
 316.154 -    }
 316.155 -
 316.156 -    @Factory
 316.157 -    public static Object[] create() {
 316.158 -        return VMTest.create(CompareStringsTest.class);
 316.159 -    }
 316.160 -
 316.161 -    private static final class NullField {
 316.162 -
 316.163 -        String name;
 316.164 -    }
 316.165 -}
   317.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/HttpResourceTest.java	Wed Feb 27 17:50:47 2013 +0100
   317.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   317.3 @@ -1,106 +0,0 @@
   317.4 -/**
   317.5 - * Back 2 Browser Bytecode Translator
   317.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   317.7 - *
   317.8 - * This program is free software: you can redistribute it and/or modify
   317.9 - * it under the terms of the GNU General Public License as published by
  317.10 - * the Free Software Foundation, version 2 of the License.
  317.11 - *
  317.12 - * This program is distributed in the hope that it will be useful,
  317.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  317.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  317.15 - * GNU General Public License for more details.
  317.16 - *
  317.17 - * You should have received a copy of the GNU General Public License
  317.18 - * along with this program. Look for COPYING file in the top folder.
  317.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  317.20 - */
  317.21 -package org.apidesign.bck2brwsr.tck;
  317.22 -
  317.23 -import java.io.InputStream;
  317.24 -import java.net.URL;
  317.25 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  317.26 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  317.27 -import org.apidesign.bck2brwsr.vmtest.Http;
  317.28 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  317.29 -import org.testng.annotations.Factory;
  317.30 -
  317.31 -/**
  317.32 - *
  317.33 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  317.34 - */
  317.35 -public class HttpResourceTest {
  317.36 -    
  317.37 -    @Http({
  317.38 -        @Http.Resource(path = "/xhr", content = "Hello Brwsr!", mimeType = "text/plain")
  317.39 -    })
  317.40 -    @BrwsrTest
  317.41 -    
  317.42 -    
  317.43 -    public String testReadContentViaXHR() throws Exception {
  317.44 -        String msg = read("/xhr");
  317.45 -        assert "Hello Brwsr!".equals(msg) : "The message was " + msg;
  317.46 -        return msg;
  317.47 -    }
  317.48 -
  317.49 -    @Http({
  317.50 -        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
  317.51 -    })
  317.52 -    @BrwsrTest
  317.53 -    public String testReadContentViaURL() throws Exception {
  317.54 -        URL url = new URL("http:/url");
  317.55 -        String msg = (String) url.getContent();
  317.56 -        assert "Hello via URL!".equals(msg) : "The message was " + msg;
  317.57 -        return msg;
  317.58 -    }
  317.59 -    @Http({
  317.60 -        @Http.Resource(path = "/url", content = "Hello via URL!", mimeType = "text/plain")
  317.61 -    })
  317.62 -    @BrwsrTest
  317.63 -    public String testReadContentViaURLWithStringParam() throws Exception {
  317.64 -        URL url = new URL("http:/url");
  317.65 -        String msg = (String) url.getContent(new Class[] { String.class });
  317.66 -        assert "Hello via URL!".equals(msg) : "The message was " + msg;
  317.67 -        return msg;
  317.68 -    }
  317.69 -
  317.70 -    @Http({
  317.71 -        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
  317.72 -    })
  317.73 -    @BrwsrTest
  317.74 -    public void testReadByte() throws Exception {
  317.75 -        URL url = new URL("http:/bytes");
  317.76 -        final Object res = url.getContent(new Class[] { byte[].class });
  317.77 -        assert res instanceof byte[] : "Expecting byte[]: " + res;
  317.78 -        byte[] arr = (byte[]) res;
  317.79 -        assert arr.length == 1 : "One byte " + arr.length;
  317.80 -        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
  317.81 -    }
  317.82 -
  317.83 -    @Http({
  317.84 -        @Http.Resource(path = "/bytes", content = "", resource = "0xfe", mimeType = "x-application/binary")
  317.85 -    })
  317.86 -    @BrwsrTest
  317.87 -    public void testReadByteViaInputStream() throws Exception {
  317.88 -        URL url = new URL("http:/bytes");
  317.89 -        InputStream is = url.openStream();
  317.90 -        byte[] arr = new byte[10];
  317.91 -        int len = is.read(arr);
  317.92 -        assert len == 1 : "One byte " + len;
  317.93 -        assert arr[0] == 0xfe : "It is 0xfe: " + Integer.toHexString(arr[0]);
  317.94 -    }
  317.95 -    
  317.96 -    @JavaScriptBody(args = { "url" }, body = 
  317.97 -          "var req = new XMLHttpRequest();\n"
  317.98 -        + "req.open('GET', url, false);\n"
  317.99 -        + "req.send();\n"
 317.100 -        + "return req.responseText;"
 317.101 -    )
 317.102 -    private static native String read(String url);
 317.103 -    
 317.104 -    
 317.105 -    @Factory
 317.106 -    public static Object[] create() {
 317.107 -        return VMTest.create(HttpResourceTest.class);
 317.108 -    }
 317.109 -}
   318.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceA.java	Wed Feb 27 17:50:47 2013 +0100
   318.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   318.3 @@ -1,34 +0,0 @@
   318.4 -/**
   318.5 - * Back 2 Browser Bytecode Translator
   318.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   318.7 - *
   318.8 - * This program is free software: you can redistribute it and/or modify
   318.9 - * it under the terms of the GNU General Public License as published by
  318.10 - * the Free Software Foundation, version 2 of the License.
  318.11 - *
  318.12 - * This program is distributed in the hope that it will be useful,
  318.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  318.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  318.15 - * GNU General Public License for more details.
  318.16 - *
  318.17 - * You should have received a copy of the GNU General Public License
  318.18 - * along with this program. Look for COPYING file in the top folder.
  318.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  318.20 - */
  318.21 -package org.apidesign.bck2brwsr.tck;
  318.22 -
  318.23 -/**
  318.24 - *
  318.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  318.26 - */
  318.27 -public class InheritanceA {
  318.28 -    private String name;
  318.29 -    
  318.30 -    public void setA(String n) {
  318.31 -        this.name = n;
  318.32 -    }
  318.33 -    
  318.34 -    public String getA() {
  318.35 -        return name;
  318.36 -    }
  318.37 -}
   319.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceB.java	Wed Feb 27 17:50:47 2013 +0100
   319.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   319.3 @@ -1,34 +0,0 @@
   319.4 -/**
   319.5 - * Back 2 Browser Bytecode Translator
   319.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   319.7 - *
   319.8 - * This program is free software: you can redistribute it and/or modify
   319.9 - * it under the terms of the GNU General Public License as published by
  319.10 - * the Free Software Foundation, version 2 of the License.
  319.11 - *
  319.12 - * This program is distributed in the hope that it will be useful,
  319.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  319.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  319.15 - * GNU General Public License for more details.
  319.16 - *
  319.17 - * You should have received a copy of the GNU General Public License
  319.18 - * along with this program. Look for COPYING file in the top folder.
  319.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  319.20 - */
  319.21 -package org.apidesign.bck2brwsr.tck;
  319.22 -
  319.23 -/**
  319.24 - *
  319.25 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  319.26 - */
  319.27 -public class InheritanceB extends InheritanceA {
  319.28 -    private String name;
  319.29 -    
  319.30 -    public void setB(String n) {
  319.31 -        this.name = n;
  319.32 -    }
  319.33 -    
  319.34 -    public String getB() {
  319.35 -        return name;
  319.36 -    }
  319.37 -}
   320.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/InheritanceTest.java	Wed Feb 27 17:50:47 2013 +0100
   320.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   320.3 @@ -1,41 +0,0 @@
   320.4 -/**
   320.5 - * Back 2 Browser Bytecode Translator
   320.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   320.7 - *
   320.8 - * This program is free software: you can redistribute it and/or modify
   320.9 - * it under the terms of the GNU General Public License as published by
  320.10 - * the Free Software Foundation, version 2 of the License.
  320.11 - *
  320.12 - * This program is distributed in the hope that it will be useful,
  320.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  320.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  320.15 - * GNU General Public License for more details.
  320.16 - *
  320.17 - * You should have received a copy of the GNU General Public License
  320.18 - * along with this program. Look for COPYING file in the top folder.
  320.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  320.20 - */
  320.21 -package org.apidesign.bck2brwsr.tck;
  320.22 -
  320.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  320.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  320.25 -import org.testng.annotations.Factory;
  320.26 -
  320.27 -/**
  320.28 - *
  320.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  320.30 - */
  320.31 -public class InheritanceTest {
  320.32 -
  320.33 -    @Compare public String checkFieldsIndependent() throws ClassNotFoundException {
  320.34 -        InheritanceB ib = new InheritanceB();
  320.35 -        ib.setA("A");
  320.36 -        ib.setB("B");
  320.37 -        return "A: " + ib.getA() + " B: " + ib.getB();
  320.38 -    }
  320.39 -    
  320.40 -    @Factory
  320.41 -    public static Object[] create() {
  320.42 -        return VMTest.create(InheritanceTest.class);
  320.43 -    }
  320.44 -}
   321.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/IntegerArithmeticTest.java	Wed Feb 27 17:50:47 2013 +0100
   321.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   321.3 @@ -1,166 +0,0 @@
   321.4 -/**
   321.5 - * Back 2 Browser Bytecode Translator
   321.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   321.7 - *
   321.8 - * This program is free software: you can redistribute it and/or modify
   321.9 - * it under the terms of the GNU General Public License as published by
  321.10 - * the Free Software Foundation, version 2 of the License.
  321.11 - *
  321.12 - * This program is distributed in the hope that it will be useful,
  321.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  321.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  321.15 - * GNU General Public License for more details.
  321.16 - *
  321.17 - * You should have received a copy of the GNU General Public License
  321.18 - * along with this program. Look for COPYING file in the top folder.
  321.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  321.20 - */
  321.21 -package org.apidesign.bck2brwsr.tck;
  321.22 -
  321.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  321.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  321.25 -import org.testng.annotations.Factory;
  321.26 -
  321.27 -/**
  321.28 - *
  321.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  321.30 - */
  321.31 -public class IntegerArithmeticTest {
  321.32 -    
  321.33 -    private static int add(int x, int y) {
  321.34 -        return x + y;
  321.35 -    }
  321.36 -    
  321.37 -    private static int sub(int x, int y) {
  321.38 -        return x - y;
  321.39 -    }
  321.40 -    
  321.41 -    private static int mul(int x, int y) {
  321.42 -        return x * y;
  321.43 -    }
  321.44 -    
  321.45 -    private static int div(int x, int y) {
  321.46 -        return x / y;
  321.47 -    }
  321.48 -    
  321.49 -    private static int mod(int x, int y) {
  321.50 -        return x % y;
  321.51 -    }
  321.52 -    
  321.53 -    private static int neg(int x) {
  321.54 -        return (-x);
  321.55 -    }
  321.56 -
  321.57 -    private static float fadd(float x, float y) {
  321.58 -        return x + y;
  321.59 -    }
  321.60 -
  321.61 -    private static double dadd(double x, double y) {
  321.62 -        return x + y;
  321.63 -    }
  321.64 -    
  321.65 -    @Compare public int addOverflow() {
  321.66 -        return add(Integer.MAX_VALUE, 1);
  321.67 -    }
  321.68 -    
  321.69 -    @Compare public int subUnderflow() {
  321.70 -        return sub(Integer.MIN_VALUE, 1);
  321.71 -    }
  321.72 -    
  321.73 -    @Compare public int addMaxIntAndMaxInt() {
  321.74 -        return add(Integer.MAX_VALUE, Integer.MAX_VALUE);
  321.75 -    }
  321.76 -    
  321.77 -    @Compare public int subMinIntAndMinInt() {
  321.78 -        return sub(Integer.MIN_VALUE, Integer.MIN_VALUE);
  321.79 -    }
  321.80 -    
  321.81 -    @Compare public int multiplyMaxInt() {
  321.82 -        return mul(Integer.MAX_VALUE, 2);
  321.83 -    }
  321.84 -    
  321.85 -    @Compare public int multiplyMaxIntAndMaxInt() {
  321.86 -        return mul(Integer.MAX_VALUE, Integer.MAX_VALUE);
  321.87 -    }
  321.88 -    
  321.89 -    @Compare public int multiplyMinInt() {
  321.90 -        return mul(Integer.MIN_VALUE, 2);
  321.91 -    }
  321.92 -    
  321.93 -    @Compare public int multiplyMinIntAndMinInt() {
  321.94 -        return mul(Integer.MIN_VALUE, Integer.MIN_VALUE);
  321.95 -    }
  321.96 -    
  321.97 -    @Compare public int multiplyPrecision() {
  321.98 -        return mul(119106029, 1103515245);
  321.99 -    }
 321.100 -    
 321.101 -    @Compare public int division() {
 321.102 -        return div(1, 2);
 321.103 -    }
 321.104 -
 321.105 -    @Compare public int divisionReminder() {
 321.106 -        return mod(1, 2);
 321.107 -    }
 321.108 -
 321.109 -    @Compare public int negativeDivision() {
 321.110 -        return div(-7, 3);
 321.111 -    }
 321.112 -
 321.113 -    @Compare public int negativeDivisionReminder() {
 321.114 -        return mod(-7, 3);
 321.115 -    }
 321.116 -
 321.117 -    @Compare public int conversionFromFloat() {
 321.118 -        return (int) fadd(-2, -0.6f);
 321.119 -    }
 321.120 -
 321.121 -    @Compare public int conversionFromDouble() {
 321.122 -        return (int) dadd(-2, -0.6);
 321.123 -    }
 321.124 -
 321.125 -    @Compare public boolean divByZeroThrowsArithmeticException() {
 321.126 -        try {
 321.127 -            div(1, 0);
 321.128 -            return false;
 321.129 -        } catch (final ArithmeticException e) {
 321.130 -            return true;
 321.131 -        }
 321.132 -    }
 321.133 -
 321.134 -    @Compare public boolean modByZeroThrowsArithmeticException() {
 321.135 -        try {
 321.136 -            mod(1, 0);
 321.137 -            return false;
 321.138 -        } catch (final ArithmeticException e) {
 321.139 -            return true;
 321.140 -        }
 321.141 -    }
 321.142 -
 321.143 -    @Compare public int negate() {
 321.144 -        return neg(123456);
 321.145 -    }
 321.146 -    
 321.147 -    @Compare public int negateMaxInt() {
 321.148 -        return neg(Integer.MAX_VALUE);
 321.149 -    }
 321.150 -    
 321.151 -    @Compare public int negateMinInt() {
 321.152 -        return neg(Integer.MIN_VALUE);
 321.153 -    }
 321.154 -    
 321.155 -    @Compare public int sumTwoDimensions() {
 321.156 -        int[][] matrix = createMatrix(4, 3);
 321.157 -        matrix[0][0] += 10;
 321.158 -        return matrix[0][0];
 321.159 -    }
 321.160 -    
 321.161 -    static int[][] createMatrix(int x, int y) {
 321.162 -        return new int[x][y];
 321.163 -    }
 321.164 -    
 321.165 -    @Factory
 321.166 -    public static Object[] create() {
 321.167 -        return VMTest.create(IntegerArithmeticTest.class);
 321.168 -    }
 321.169 -}
   322.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/LongArithmeticTest.java	Wed Feb 27 17:50:47 2013 +0100
   322.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   322.3 @@ -1,376 +0,0 @@
   322.4 -/**
   322.5 - * Back 2 Browser Bytecode Translator
   322.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   322.7 - *
   322.8 - * This program is free software: you can redistribute it and/or modify
   322.9 - * it under the terms of the GNU General Public License as published by
  322.10 - * the Free Software Foundation, version 2 of the License.
  322.11 - *
  322.12 - * This program is distributed in the hope that it will be useful,
  322.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  322.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  322.15 - * GNU General Public License for more details.
  322.16 - *
  322.17 - * You should have received a copy of the GNU General Public License
  322.18 - * along with this program. Look for COPYING file in the top folder.
  322.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  322.20 - */
  322.21 -package org.apidesign.bck2brwsr.tck;
  322.22 -
  322.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  322.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  322.25 -import org.testng.annotations.Factory;
  322.26 -
  322.27 -/**
  322.28 - *
  322.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  322.30 - */
  322.31 -public class LongArithmeticTest {
  322.32 -
  322.33 -    private static long add(long x, long y) {
  322.34 -        return (x + y);
  322.35 -    }
  322.36 -
  322.37 -    private static long sub(long x, long y) {
  322.38 -        return (x - y);
  322.39 -    }
  322.40 -
  322.41 -    private static long mul(long x, long y) {
  322.42 -        return (x * y);
  322.43 -    }
  322.44 -
  322.45 -    private static long div(long x, long y) {
  322.46 -        return (x / y);
  322.47 -    }
  322.48 -
  322.49 -    private static long mod(long x, long y) {
  322.50 -        return (x % y);
  322.51 -    }
  322.52 -
  322.53 -    private static long neg(long x) {
  322.54 -        return (-x);
  322.55 -    }
  322.56 -
  322.57 -    private static long shl(long x, int b) {
  322.58 -        return (x << b);
  322.59 -    }
  322.60 -
  322.61 -    private static long shr(long x, int b) {
  322.62 -        return (x >> b);
  322.63 -    }
  322.64 -
  322.65 -    private static long ushr(long x, int b) {
  322.66 -        return (x >>> b);
  322.67 -    }
  322.68 -
  322.69 -    private static long and(long x, long y) {
  322.70 -        return (x & y);
  322.71 -    }
  322.72 -
  322.73 -    private static long or(long x, long y) {
  322.74 -        return (x | y);
  322.75 -    }
  322.76 -
  322.77 -    private static long xor(long x, long y) {
  322.78 -        return (x ^ y);
  322.79 -    }
  322.80 -
  322.81 -    private static float fadd(float x, float y) {
  322.82 -        return x + y;
  322.83 -    }
  322.84 -
  322.85 -    private static double dadd(double x, double y) {
  322.86 -        return x + y;
  322.87 -    }
  322.88 -
  322.89 -    public static int compare(long x, long y, int zero) {
  322.90 -        final int xyResult = compareL(x, y, zero);
  322.91 -        final int yxResult = compareL(y, x, zero);
  322.92 -
  322.93 -        return ((xyResult + yxResult) == 0) ? xyResult : -2;
  322.94 -    }
  322.95 -
  322.96 -    private static int compareL(long x, long y, int zero) {
  322.97 -        int result = -2;
  322.98 -        int trueCount = 0;
  322.99 -
 322.100 -        x += zero;
 322.101 -        if (x == y) {
 322.102 -            result = 0;
 322.103 -            ++trueCount;
 322.104 -        }
 322.105 -
 322.106 -        x += zero;
 322.107 -        if (x < y) {
 322.108 -            result = -1;
 322.109 -            ++trueCount;
 322.110 -        }
 322.111 -
 322.112 -        x += zero;
 322.113 -        if (x > y) {
 322.114 -            result = 1;
 322.115 -            ++trueCount;
 322.116 -        }
 322.117 -
 322.118 -        return (trueCount == 1) ? result : -2;
 322.119 -    }
 322.120 -
 322.121 -    @Compare public long conversion() {
 322.122 -        return Long.MAX_VALUE;
 322.123 -    }
 322.124 -
 322.125 -    @Compare public long negate1() {
 322.126 -        return neg(0x00fa37d7763e0ca1l);
 322.127 -    }
 322.128 -
 322.129 -    @Compare public long negate2() {
 322.130 -        return neg(0x80fa37d7763e0ca1l);
 322.131 -    }
 322.132 -
 322.133 -    @Compare public long negate3() {
 322.134 -        return neg(0xfffffffffffffeddl);
 322.135 -    }
 322.136 -
 322.137 -    @Compare public long addOverflow() {
 322.138 -        return add(Long.MAX_VALUE, 1l);
 322.139 -    }
 322.140 -
 322.141 -    @Compare public long subUnderflow() {
 322.142 -        return sub(Long.MIN_VALUE, 1l);
 322.143 -    }
 322.144 -
 322.145 -    @Compare public long addMaxLongAndMaxLong() {
 322.146 -        return add(Long.MAX_VALUE, Long.MAX_VALUE);
 322.147 -    }
 322.148 -
 322.149 -    @Compare public long subMinLongAndMinLong() {
 322.150 -        return sub(Long.MIN_VALUE, Long.MIN_VALUE);
 322.151 -    }
 322.152 -
 322.153 -    @Compare public long subMinLongAndMaxLong() {
 322.154 -        return sub(Long.MIN_VALUE, Long.MAX_VALUE);
 322.155 -    }
 322.156 -
 322.157 -    @Compare public long multiplyMaxLong() {
 322.158 -        return mul(Long.MAX_VALUE, 2l);
 322.159 -    }
 322.160 -
 322.161 -    @Compare public long multiplyMaxLongAndMaxLong() {
 322.162 -        return mul(Long.MAX_VALUE, Long.MAX_VALUE);
 322.163 -    }
 322.164 -
 322.165 -    @Compare public long multiplyMinLong() {
 322.166 -        return mul(Long.MIN_VALUE, 2l);
 322.167 -    }
 322.168 -
 322.169 -    @Compare public long multiplyMinLongAndMinLong() {
 322.170 -        return mul(Long.MIN_VALUE, Long.MIN_VALUE);
 322.171 -    }
 322.172 -
 322.173 -    @Compare public long multiplyPrecision() {
 322.174 -        return mul(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 322.175 -    }
 322.176 -
 322.177 -    @Compare public long divideSmallPositiveNumbers() {
 322.178 -        return div(0xabcdef, 0x123);
 322.179 -    }
 322.180 -
 322.181 -    @Compare public long divideSmallNegativeNumbers() {
 322.182 -        return div(-0xabcdef, -0x123);
 322.183 -    }
 322.184 -
 322.185 -    @Compare public long divideSmallMixedNumbers() {
 322.186 -        return div(0xabcdef, -0x123);
 322.187 -    }
 322.188 -
 322.189 -    @Compare public long dividePositiveNumbersOneDigitDenom() {
 322.190 -        return div(0xabcdef0102ffffl, 0x654);
 322.191 -    }
 322.192 -
 322.193 -    @Compare public long divideNegativeNumbersOneDigitDenom() {
 322.194 -        return div(-0xabcdef0102ffffl, -0x654);
 322.195 -    }
 322.196 -
 322.197 -    @Compare public long divideMixedNumbersOneDigitDenom() {
 322.198 -        return div(-0xabcdef0102ffffl, 0x654);
 322.199 -    }
 322.200 -
 322.201 -    @Compare public long dividePositiveNumbersMultiDigitDenom() {
 322.202 -        return div(0x7ffefc003322aabbl, 0x89ab1000l);
 322.203 -    }
 322.204 -
 322.205 -    @Compare public long divideNegativeNumbersMultiDigitDenom() {
 322.206 -        return div(-0x7ffefc003322aabbl, -0x123489ab1001l);
 322.207 -    }
 322.208 -
 322.209 -    @Compare public long divideMixedNumbersMultiDigitDenom() {
 322.210 -        return div(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
 322.211 -    }
 322.212 -
 322.213 -    @Compare public long divideWithOverflow() {
 322.214 -        return div(0x8000fffe0000l, 0x8000ffffl);
 322.215 -    }
 322.216 -
 322.217 -    @Compare public long divideWithCorrection() {
 322.218 -        return div(0x7fff800000000000l, 0x800000000001l);
 322.219 -    }
 322.220 -
 322.221 -    @Compare public long moduloSmallPositiveNumbers() {
 322.222 -        return mod(0xabcdef, 0x123);
 322.223 -    }
 322.224 -
 322.225 -    @Compare public long moduloSmallNegativeNumbers() {
 322.226 -        return mod(-0xabcdef, -0x123);
 322.227 -    }
 322.228 -
 322.229 -    @Compare public long moduloSmallMixedNumbers() {
 322.230 -        return mod(0xabcdef, -0x123);
 322.231 -    }
 322.232 -
 322.233 -    @Compare public long moduloPositiveNumbersOneDigitDenom() {
 322.234 -        return mod(0xabcdef0102ffffl, 0x654);
 322.235 -    }
 322.236 -
 322.237 -    @Compare public long moduloNegativeNumbersOneDigitDenom() {
 322.238 -        return mod(-0xabcdef0102ffffl, -0x654);
 322.239 -    }
 322.240 -
 322.241 -    @Compare public long moduloMixedNumbersOneDigitDenom() {
 322.242 -        return mod(-0xabcdef0102ffffl, 0x654);
 322.243 -    }
 322.244 -
 322.245 -    @Compare public long moduloPositiveNumbersMultiDigitDenom() {
 322.246 -        return mod(0x7ffefc003322aabbl, 0x89ab1000l);
 322.247 -    }
 322.248 -
 322.249 -    @Compare public long moduloNegativeNumbersMultiDigitDenom() {
 322.250 -        return mod(-0x7ffefc003322aabbl, -0x123489ab1001l);
 322.251 -    }
 322.252 -
 322.253 -    @Compare public long moduloMixedNumbersMultiDigitDenom() {
 322.254 -        return mod(0x7ffefc003322aabbl, -0x38f49b0b7574e36l);
 322.255 -    }
 322.256 -
 322.257 -    @Compare public long moduloWithOverflow() {
 322.258 -        return mod(0x8000fffe0000l, 0x8000ffffl);
 322.259 -    }
 322.260 -
 322.261 -    @Compare public long moduloWithCorrection() {
 322.262 -        return mod(0x7fff800000000000l, 0x800000000001l);
 322.263 -    }
 322.264 -
 322.265 -    @Compare public long conversionFromFloatPositive() {
 322.266 -        return (long) fadd(2, 0.6f);
 322.267 -    }
 322.268 -
 322.269 -    @Compare public long conversionFromFloatNegative() {
 322.270 -        return (long) fadd(-2, -0.6f);
 322.271 -    }
 322.272 -
 322.273 -    @Compare public long conversionFromDoublePositive() {
 322.274 -        return (long) dadd(0x20ffff0000L, 0.6);
 322.275 -    }
 322.276 -
 322.277 -    @Compare public long conversionFromDoubleNegative() {
 322.278 -        return (long) dadd(-0x20ffff0000L, -0.6);
 322.279 -    }
 322.280 -
 322.281 -    @Compare public boolean divByZeroThrowsArithmeticException() {
 322.282 -        try {
 322.283 -            div(1, 0);
 322.284 -            return false;
 322.285 -        } catch (final ArithmeticException e) {
 322.286 -            return true;
 322.287 -        }
 322.288 -    }
 322.289 -
 322.290 -    @Compare public boolean modByZeroThrowsArithmeticException() {
 322.291 -        try {
 322.292 -            mod(1, 0);
 322.293 -            return false;
 322.294 -        } catch (final ArithmeticException e) {
 322.295 -            return true;
 322.296 -        }
 322.297 -    }
 322.298 -
 322.299 -    @Compare public long shiftL1() {
 322.300 -        return shl(0x00fa37d7763e0ca1l, 5);
 322.301 -    }
 322.302 -
 322.303 -    @Compare public long shiftL2() {
 322.304 -        return shl(0x00fa37d7763e0ca1l, 32);
 322.305 -    }
 322.306 -
 322.307 -    @Compare public long shiftL3() {
 322.308 -        return shl(0x00fa37d7763e0ca1l, 45);
 322.309 -    }
 322.310 -
 322.311 -    @Compare public long shiftR1() {
 322.312 -        return shr(0x00fa37d7763e0ca1l, 5);
 322.313 -    }
 322.314 -
 322.315 -    @Compare public long shiftR2() {
 322.316 -        return shr(0x00fa37d7763e0ca1l, 32);
 322.317 -    }
 322.318 -
 322.319 -    @Compare public long shiftR3() {
 322.320 -        return shr(0x00fa37d7763e0ca1l, 45);
 322.321 -    }
 322.322 -
 322.323 -    @Compare public long uShiftR1() {
 322.324 -        return ushr(0x00fa37d7763e0ca1l, 5);
 322.325 -    }
 322.326 -
 322.327 -    @Compare public long uShiftR2() {
 322.328 -        return ushr(0x00fa37d7763e0ca1l, 45);
 322.329 -    }
 322.330 -
 322.331 -    @Compare public long uShiftR3() {
 322.332 -        return ushr(0xf0fa37d7763e0ca1l, 5);
 322.333 -    }
 322.334 -
 322.335 -    @Compare public long uShiftR4() {
 322.336 -        return ushr(0xf0fa37d7763e0ca1l, 45);
 322.337 -    }
 322.338 -
 322.339 -    @Compare public long and1() {
 322.340 -        return and(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 322.341 -    }
 322.342 -
 322.343 -    @Compare public long or1() {
 322.344 -        return or(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 322.345 -    }
 322.346 -
 322.347 -    @Compare public long xor1() {
 322.348 -        return xor(0x00fa37d7763e0ca1l, 0xa7b3432fff00123el);
 322.349 -    }
 322.350 -
 322.351 -    @Compare public long xor2() {
 322.352 -        return xor(0x00fa37d7763e0ca1l, 0x00000000ff00123el);
 322.353 -    }
 322.354 -
 322.355 -    @Compare public long xor3() {
 322.356 -        return xor(0x00000000763e0ca1l, 0x00000000ff00123el);
 322.357 -    }
 322.358 -
 322.359 -    @Compare public int compareSameNumbers() {
 322.360 -        return compare(0x0000000000000000l, 0x0000000000000000l, 0);
 322.361 -    }
 322.362 -
 322.363 -    @Compare public int comparePositiveNumbers() {
 322.364 -        return compare(0x0000000000200000l, 0x0000000010000000l, 0);
 322.365 -    }
 322.366 -
 322.367 -    @Compare public int compareNegativeNumbers() {
 322.368 -        return compare(0xffffffffffffffffl, 0xffffffff00000000l, 0);
 322.369 -    }
 322.370 -
 322.371 -    @Compare public int compareMixedNumbers() {
 322.372 -        return compare(0x8000000000000000l, 0x7fffffffffffffffl, 0);
 322.373 -    }
 322.374 -    
 322.375 -    @Factory
 322.376 -    public static Object[] create() {
 322.377 -        return VMTest.create(LongArithmeticTest.class);
 322.378 -    }
 322.379 -}
   323.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionArrayTest.java	Wed Feb 27 17:50:47 2013 +0100
   323.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   323.3 @@ -1,135 +0,0 @@
   323.4 -/**
   323.5 - * Back 2 Browser Bytecode Translator
   323.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   323.7 - *
   323.8 - * This program is free software: you can redistribute it and/or modify
   323.9 - * it under the terms of the GNU General Public License as published by
  323.10 - * the Free Software Foundation, version 2 of the License.
  323.11 - *
  323.12 - * This program is distributed in the hope that it will be useful,
  323.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  323.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  323.15 - * GNU General Public License for more details.
  323.16 - *
  323.17 - * You should have received a copy of the GNU General Public License
  323.18 - * along with this program. Look for COPYING file in the top folder.
  323.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  323.20 - */
  323.21 -package org.apidesign.bck2brwsr.tck;
  323.22 -
  323.23 -import java.lang.reflect.Array;
  323.24 -import org.apidesign.bck2brwsr.vmtest.Compare;
  323.25 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  323.26 -import org.testng.annotations.Factory;
  323.27 -
  323.28 -/**
  323.29 - *
  323.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  323.31 - */
  323.32 -public class ReflectionArrayTest {
  323.33 -    @Compare public int lengthOfStringArray() {
  323.34 -        String[] arr = (String[]) Array.newInstance(String.class, 10);
  323.35 -        return arr.length;
  323.36 -    }
  323.37 -    
  323.38 -    @Compare public int reflectiveLengthOfStringArray() {
  323.39 -        Object arr = Array.newInstance(String.class, 10);
  323.40 -        return Array.getLength(arr);
  323.41 -    }
  323.42 -
  323.43 -    @Compare public int reflectiveLengthOneNonArray() {
  323.44 -        Object arr = "non-array";
  323.45 -        return Array.getLength(arr);
  323.46 -    }
  323.47 -
  323.48 -    @Compare public String compTypeOfStringArray() {
  323.49 -        String[] arr = (String[]) Array.newInstance(String.class, 10);
  323.50 -        return arr.getClass().getComponentType().getName();
  323.51 -    }
  323.52 -
  323.53 -    @Compare public Object negativeArrayExcp() {
  323.54 -        return Array.newInstance(String.class, -5);
  323.55 -    }
  323.56 -    
  323.57 -    @Compare public int lengthOfIntArray() {
  323.58 -        int[] arr = (int[]) Array.newInstance(Integer.TYPE, 10);
  323.59 -        return arr.length;
  323.60 -    }
  323.61 -
  323.62 -    @Compare public int reflectiveLengthOfIntArray() {
  323.63 -        Object arr = Array.newInstance(Integer.TYPE, 10);
  323.64 -        return Array.getLength(arr);
  323.65 -    }
  323.66 -
  323.67 -    @Compare public String compTypeOfIntArray() {
  323.68 -        int[] arr = (int[]) Array.newInstance(int.class, 10);
  323.69 -        return arr.getClass().getComponentType().getName();
  323.70 -    }
  323.71 -
  323.72 -    @Compare public Object intNegativeArrayExcp() {
  323.73 -        return Array.newInstance(int.class, -5);
  323.74 -    }
  323.75 -
  323.76 -    @Compare public Integer verifyAutobox() {
  323.77 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
  323.78 -        return (Integer) Array.get(arr, 0);
  323.79 -    }
  323.80 -    @Compare public String verifyObjectArray() {
  323.81 -        String[] arr = (String[]) Array.newInstance(String.class, 5);
  323.82 -        Array.set(arr, 0, "Hello");
  323.83 -        return (String) Array.get(arr, 0);
  323.84 -    }
  323.85 -    @Compare public int verifyInt() {
  323.86 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
  323.87 -        return Array.getInt(arr, 0);
  323.88 -    }
  323.89 -    @Compare public long verifyConvertToLong() {
  323.90 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
  323.91 -        return Array.getLong(arr, 0);
  323.92 -    }
  323.93 -
  323.94 -    @Compare public Object verifySetIntToObject() {
  323.95 -        try {
  323.96 -            Object[] arr = (Object[]) Array.newInstance(Object.class, 5);
  323.97 -            Array.setInt(arr, 0, 10);
  323.98 -            return Array.get(arr, 0);
  323.99 -        } catch (Exception exception) {
 323.100 -            return exception.getClass().getName();
 323.101 -        }
 323.102 -    }
 323.103 -    @Compare public long verifySetShort() {
 323.104 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
 323.105 -        Array.setShort(arr, 0, (short)10);
 323.106 -        return Array.getLong(arr, 0);
 323.107 -    }
 323.108 -    @Compare public long verifyCantSetLong() {
 323.109 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
 323.110 -        Array.setLong(arr, 0, 10);
 323.111 -        return Array.getLong(arr, 0);
 323.112 -    }
 323.113 -    @Compare public float verifyLongToFloat() {
 323.114 -        Object arr = Array.newInstance(float.class, 5);
 323.115 -        Array.setLong(arr, 0, 10);
 323.116 -        return Array.getFloat(arr, 0);
 323.117 -    }
 323.118 -
 323.119 -    @Compare public double verifyConvertToDouble() {
 323.120 -        int[] arr = (int[]) Array.newInstance(int.class, 5);
 323.121 -        return Array.getDouble(arr, 0);
 323.122 -    }
 323.123 -    
 323.124 -    @Compare public int multiIntArray() {
 323.125 -        int[][][] arr = (int[][][]) Array.newInstance(int.class, 3, 3, 3);
 323.126 -        return arr[0][1][2] + 5 + arr[2][2][0];
 323.127 -    }
 323.128 -
 323.129 -    @Compare public String multiIntArrayCompType() {
 323.130 -        return Array.newInstance(int.class, 3, 3, 3).getClass().getName();
 323.131 -    }
 323.132 -    
 323.133 -    
 323.134 -    @Factory
 323.135 -    public static Object[] create() {
 323.136 -        return VMTest.create(ReflectionArrayTest.class);
 323.137 -    }
 323.138 -}
   324.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ReflectionTest.java	Wed Feb 27 17:50:47 2013 +0100
   324.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   324.3 @@ -1,242 +0,0 @@
   324.4 -/**
   324.5 - * Back 2 Browser Bytecode Translator
   324.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   324.7 - *
   324.8 - * This program is free software: you can redistribute it and/or modify
   324.9 - * it under the terms of the GNU General Public License as published by
  324.10 - * the Free Software Foundation, version 2 of the License.
  324.11 - *
  324.12 - * This program is distributed in the hope that it will be useful,
  324.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  324.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  324.15 - * GNU General Public License for more details.
  324.16 - *
  324.17 - * You should have received a copy of the GNU General Public License
  324.18 - * along with this program. Look for COPYING file in the top folder.
  324.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  324.20 - */
  324.21 -package org.apidesign.bck2brwsr.tck;
  324.22 -
  324.23 -import java.lang.annotation.Retention;
  324.24 -import java.lang.annotation.RetentionPolicy;
  324.25 -import java.lang.reflect.Method;
  324.26 -import java.util.Arrays;
  324.27 -import java.util.Collections;
  324.28 -import java.util.List;
  324.29 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  324.30 -import org.apidesign.bck2brwsr.vmtest.Compare;
  324.31 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  324.32 -import org.testng.annotations.Factory;
  324.33 -
  324.34 -/**
  324.35 - *
  324.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  324.37 - */
  324.38 -public class ReflectionTest {
  324.39 -    @Compare public boolean nonNullThis() {
  324.40 -        return this == null;
  324.41 -    }
  324.42 -    
  324.43 -    @Compare public String intType() {
  324.44 -        return Integer.TYPE.toString();
  324.45 -    }
  324.46 -
  324.47 -    @Compare public String voidType() throws Exception {
  324.48 -        return void.class.toString();
  324.49 -    }
  324.50 -
  324.51 -    @Compare public String longClass() {
  324.52 -        return long.class.toString();
  324.53 -    }
  324.54 -    
  324.55 -    @Compare public boolean isRunnableInterface() {
  324.56 -        return Runnable.class.isInterface();
  324.57 -    }
  324.58 -
  324.59 -    @Compare public String isRunnableHasRunMethod() throws NoSuchMethodException {
  324.60 -        return Runnable.class.getMethod("run").getName();
  324.61 -    }
  324.62 -    
  324.63 -    @Compare public String namesOfMethods() {
  324.64 -        StringBuilder sb = new StringBuilder();
  324.65 -        String[] arr = new String[20];
  324.66 -        int i = 0;
  324.67 -        for (Method m : StaticUse.class.getMethods()) {
  324.68 -            arr[i++] = m.getName();
  324.69 -        }
  324.70 -        for (String s : sort(arr, i)) {
  324.71 -            sb.append(s).append("\n");
  324.72 -        }
  324.73 -        return sb.toString();
  324.74 -    }
  324.75 -
  324.76 -    @Compare public String namesOfDeclaringClassesOfMethods() {
  324.77 -        StringBuilder sb = new StringBuilder();
  324.78 -        String[] arr = new String[20];
  324.79 -        int i = 0;
  324.80 -        for (Method m : StaticUse.class.getMethods()) {
  324.81 -            arr[i++] = m.getName() + "@" + m.getDeclaringClass().getName();
  324.82 -        }
  324.83 -        for (String s : sort(arr, i)) {
  324.84 -            sb.append(s).append("\n");
  324.85 -        }
  324.86 -        return sb.toString();
  324.87 -    }
  324.88 -    
  324.89 -    @Compare public String cannotCallNonStaticMethodWithNull() throws Exception {
  324.90 -        StaticUse.class.getMethod("instanceMethod").invoke(null);
  324.91 -        return "should not happen";
  324.92 -    }
  324.93 -
  324.94 -    @Compare public Object voidReturnType() throws Exception {
  324.95 -        return StaticUse.class.getMethod("instanceMethod").getReturnType();
  324.96 -    }
  324.97 -    
  324.98 -    @Retention(RetentionPolicy.RUNTIME)
  324.99 -    @interface Ann {
 324.100 -    }
 324.101 -    
 324.102 -    @Compare public String annoClass() throws Exception {
 324.103 -        Retention r = Ann.class.getAnnotation(Retention.class);
 324.104 -        assert r != null : "Annotation is present";
 324.105 -        assert r.value() == RetentionPolicy.RUNTIME : "Policy value is OK: " + r.value();
 324.106 -        return r.annotationType().getName();
 324.107 -    }
 324.108 -    
 324.109 -    @Compare public boolean isAnnotation() {
 324.110 -        return Ann.class.isAnnotation();
 324.111 -    }
 324.112 -    @Compare public boolean isNotAnnotation() {
 324.113 -        return String.class.isAnnotation();
 324.114 -    }
 324.115 -    @Compare public boolean isNotAnnotationEnum() {
 324.116 -        return E.class.isAnnotation();
 324.117 -    }
 324.118 -    enum E { A, B };
 324.119 -    @Compare public boolean isEnum() {
 324.120 -        return E.A.getClass().isEnum();
 324.121 -    }
 324.122 -
 324.123 -    @Compare public boolean isNotEnum() {
 324.124 -        return "".getClass().isEnum();
 324.125 -    }
 324.126 -    
 324.127 -    @Compare public String newInstanceFails() throws InstantiationException {
 324.128 -        try {
 324.129 -            return "success: " + StaticUse.class.newInstance();
 324.130 -        } catch (IllegalAccessException ex) {
 324.131 -            return ex.getClass().getName();
 324.132 -        }
 324.133 -    }
 324.134 -    
 324.135 -    @Compare public String paramTypes() throws Exception {
 324.136 -        Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
 324.137 -        final Class[] pt = plus.getParameterTypes();
 324.138 -        return pt[0].getName();
 324.139 -    }
 324.140 -    @Compare public String paramTypesNotFound() throws Exception {
 324.141 -        return StaticUse.class.getMethod("plus", int.class, double.class).toString();
 324.142 -    }
 324.143 -    @Compare public int methodWithArgs() throws Exception {
 324.144 -        Method plus = StaticUse.class.getMethod("plus", int.class, Integer.TYPE);
 324.145 -        return (Integer)plus.invoke(null, 2, 3);
 324.146 -    }
 324.147 -    
 324.148 -    @Compare public String classGetNameForByte() {
 324.149 -         return byte.class.getName();
 324.150 -    }
 324.151 -    @Compare public String classGetNameForBaseObject() {
 324.152 -        return newObject().getClass().getName();
 324.153 -    }
 324.154 -    @Compare public String classGetNameForJavaObject() {
 324.155 -        return new Object().getClass().getName();
 324.156 -    }
 324.157 -    @Compare public String classGetNameForObjectArray() {
 324.158 -        return (new Object[3]).getClass().getName();
 324.159 -    }
 324.160 -    @Compare public String classGetNameForSimpleIntArray() {
 324.161 -        return (new int[3]).getClass().getName();
 324.162 -    }
 324.163 -    @Compare public boolean sameClassGetNameForSimpleCharArray() {
 324.164 -        return (new char[3]).getClass() == (new char[34]).getClass();
 324.165 -    }
 324.166 -    @Compare public String classGetNameForMultiIntArray() {
 324.167 -        return (new int[3][4][5][6][7][8][9]).getClass().getName();
 324.168 -    }
 324.169 -    @Compare public String classGetNameForMultiIntArrayInner() {
 324.170 -        final int[][][][][][][] arr = new int[3][4][5][6][7][8][9];
 324.171 -        int[][][][][][] subarr = arr[0];
 324.172 -        int[][][][][] subsubarr = subarr[0];
 324.173 -        return subsubarr.getClass().getName();
 324.174 -    }
 324.175 -    @Compare public String classGetNameForMultiStringArray() {
 324.176 -        return (new String[3][4][5][6][7][8][9]).getClass().getName();
 324.177 -    }
 324.178 -    
 324.179 -    @Compare public String classForByte() throws Exception {
 324.180 -        return Class.forName("[Z").getName();
 324.181 -    }
 324.182 -
 324.183 -    @Compare public String classForUnknownArray() {
 324.184 -        try {
 324.185 -            return Class.forName("[W").getName();
 324.186 -        } catch (Exception ex) {
 324.187 -            return ex.getClass().getName();
 324.188 -        }
 324.189 -    }
 324.190 -    
 324.191 -    @Compare public String classForUnknownDeepArray() {
 324.192 -        try {
 324.193 -            return Class.forName("[[[[[W").getName();
 324.194 -        } catch (Exception ex) {
 324.195 -            return ex.getClass().getName();
 324.196 -        }
 324.197 -    }
 324.198 -    
 324.199 -    @Compare public String componentGetNameForObjectArray() {
 324.200 -        return (new Object[3]).getClass().getComponentType().getName();
 324.201 -    }
 324.202 -    @Compare public boolean sameComponentGetNameForObjectArray() {
 324.203 -        return (new Object[3]).getClass().getComponentType() == Object.class;
 324.204 -    }
 324.205 -    @Compare public String componentGetNameForSimpleIntArray() {
 324.206 -        return (new int[3]).getClass().getComponentType().getName();
 324.207 -    }
 324.208 -    @Compare public String componentGetNameForMultiIntArray() {
 324.209 -        return (new int[3][4][5][6][7][8][9]).getClass().getComponentType().getName();
 324.210 -    }
 324.211 -    @Compare public String componentGetNameForMultiStringArray() {
 324.212 -        Class<?> c = (new String[3][4][5][6][7][8][9]).getClass();
 324.213 -        StringBuilder sb = new StringBuilder();
 324.214 -        for (;;) {
 324.215 -            sb.append(c.getName()).append("\n");
 324.216 -            c = c.getComponentType();
 324.217 -            if (c == null) {
 324.218 -                break;
 324.219 -            }
 324.220 -        }
 324.221 -        return sb.toString();
 324.222 -    }
 324.223 -    
 324.224 -    @Compare public boolean isArray() {
 324.225 -        return new Object[0].getClass().isArray();
 324.226 -    }
 324.227 -    
 324.228 -    @JavaScriptBody(args = { "arr", "len" }, body="var a = arr.slice(0, len); a.sort(); return a;")
 324.229 -    private static String[] sort(String[] arr, int len) {
 324.230 -        List<String> list = Arrays.asList(arr).subList(0, len);
 324.231 -        Collections.sort(list);
 324.232 -        return list.toArray(new String[0]);
 324.233 -    }
 324.234 -    
 324.235 -    @JavaScriptBody(args = {}, body = "return new Object();")
 324.236 -    private static Object newObject() {
 324.237 -        return new Object();
 324.238 -    }
 324.239 -    
 324.240 -    @Factory
 324.241 -    public static Object[] create() {
 324.242 -        return VMTest.create(ReflectionTest.class);
 324.243 -    }
 324.244 -    
 324.245 -}
   325.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ResourcesTest.java	Wed Feb 27 17:50:47 2013 +0100
   325.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   325.3 @@ -1,45 +0,0 @@
   325.4 -/**
   325.5 - * Back 2 Browser Bytecode Translator
   325.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   325.7 - *
   325.8 - * This program is free software: you can redistribute it and/or modify
   325.9 - * it under the terms of the GNU General Public License as published by
  325.10 - * the Free Software Foundation, version 2 of the License.
  325.11 - *
  325.12 - * This program is distributed in the hope that it will be useful,
  325.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  325.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  325.15 - * GNU General Public License for more details.
  325.16 - *
  325.17 - * You should have received a copy of the GNU General Public License
  325.18 - * along with this program. Look for COPYING file in the top folder.
  325.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  325.20 - */
  325.21 -package org.apidesign.bck2brwsr.tck;
  325.22 -
  325.23 -import java.io.InputStream;
  325.24 -import org.apidesign.bck2brwsr.vmtest.Compare;
  325.25 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  325.26 -import org.testng.annotations.Factory;
  325.27 -
  325.28 -/**
  325.29 - *
  325.30 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  325.31 - */
  325.32 -public class ResourcesTest {
  325.33 -    
  325.34 -    @Compare public String readResourceAsStream() throws Exception {
  325.35 -        InputStream is = getClass().getResourceAsStream("Resources.txt");
  325.36 -        byte[] b = new byte[30];
  325.37 -        int len = is.read(b);
  325.38 -        StringBuilder sb = new StringBuilder();
  325.39 -        for (int i = 0; i < len; i++) {
  325.40 -            sb.append((char)b[i]);
  325.41 -        }
  325.42 -        return sb.toString();
  325.43 -    }
  325.44 -    
  325.45 -    @Factory public static Object[] create() {
  325.46 -        return VMTest.create(ResourcesTest.class);
  325.47 -    }
  325.48 -}
   326.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/ShortArithmeticTest.java	Wed Feb 27 17:50:47 2013 +0100
   326.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   326.3 @@ -1,102 +0,0 @@
   326.4 -/**
   326.5 - * Back 2 Browser Bytecode Translator
   326.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   326.7 - *
   326.8 - * This program is free software: you can redistribute it and/or modify
   326.9 - * it under the terms of the GNU General Public License as published by
  326.10 - * the Free Software Foundation, version 2 of the License.
  326.11 - *
  326.12 - * This program is distributed in the hope that it will be useful,
  326.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  326.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  326.15 - * GNU General Public License for more details.
  326.16 - *
  326.17 - * You should have received a copy of the GNU General Public License
  326.18 - * along with this program. Look for COPYING file in the top folder.
  326.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  326.20 - */
  326.21 -package org.apidesign.bck2brwsr.tck;
  326.22 -
  326.23 -import org.apidesign.bck2brwsr.vmtest.Compare;
  326.24 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  326.25 -import org.testng.annotations.Factory;
  326.26 -
  326.27 -/**
  326.28 - *
  326.29 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  326.30 - */
  326.31 -public class ShortArithmeticTest {
  326.32 -    
  326.33 -    private static short add(short x, short y) {
  326.34 -        return (short)(x + y);
  326.35 -    }
  326.36 -    
  326.37 -    private static short sub(short x, short y) {
  326.38 -        return (short)(x - y);
  326.39 -    }
  326.40 -    
  326.41 -    private static short mul(short x, short y) {
  326.42 -        return (short)(x * y);
  326.43 -    }
  326.44 -    
  326.45 -    private static short div(short x, short y) {
  326.46 -        return (short)(x / y);
  326.47 -    }
  326.48 -    
  326.49 -    private static short mod(short x, short y) {
  326.50 -        return (short)(x % y);
  326.51 -    }
  326.52 -    
  326.53 -    @Compare public short conversion() {
  326.54 -        return (short)123456;
  326.55 -    }
  326.56 -    
  326.57 -    @Compare public short addOverflow() {
  326.58 -        return add(Short.MAX_VALUE, (short)1);
  326.59 -    }
  326.60 -    
  326.61 -    @Compare public short subUnderflow() {
  326.62 -        return sub(Short.MIN_VALUE, (short)1);
  326.63 -    }
  326.64 -    
  326.65 -    @Compare public short addMaxShortAndMaxShort() {
  326.66 -        return add(Short.MAX_VALUE, Short.MAX_VALUE);
  326.67 -    }
  326.68 -    
  326.69 -    @Compare public short subMinShortAndMinShort() {
  326.70 -        return sub(Short.MIN_VALUE, Short.MIN_VALUE);
  326.71 -    }
  326.72 -    
  326.73 -    @Compare public short multiplyMaxShort() {
  326.74 -        return mul(Short.MAX_VALUE, (short)2);
  326.75 -    }
  326.76 -    
  326.77 -    @Compare public short multiplyMaxShortAndMaxShort() {
  326.78 -        return mul(Short.MAX_VALUE, Short.MAX_VALUE);
  326.79 -    }
  326.80 -    
  326.81 -    @Compare public short multiplyMinShort() {
  326.82 -        return mul(Short.MIN_VALUE, (short)2);
  326.83 -    }
  326.84 -    
  326.85 -    @Compare public short multiplyMinShortAndMinShort() {
  326.86 -        return mul(Short.MIN_VALUE, Short.MIN_VALUE);
  326.87 -    }
  326.88 -    
  326.89 -    @Compare public short multiplyPrecision() {
  326.90 -        return mul((short)17638, (short)1103);
  326.91 -    }
  326.92 -    
  326.93 -    @Compare public short division() {
  326.94 -        return div((short)1, (short)2);
  326.95 -    }
  326.96 -    
  326.97 -    @Compare public short divisionReminder() {
  326.98 -        return mod((short)1, (short)2);
  326.99 -    }
 326.100 -    
 326.101 -    @Factory
 326.102 -    public static Object[] create() {
 326.103 -        return VMTest.create(ShortArithmeticTest.class);
 326.104 -    }
 326.105 -}
   327.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/tck/StaticUse.java	Wed Feb 27 17:50:47 2013 +0100
   327.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   327.3 @@ -1,31 +0,0 @@
   327.4 -/**
   327.5 - * Back 2 Browser Bytecode Translator
   327.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   327.7 - *
   327.8 - * This program is free software: you can redistribute it and/or modify
   327.9 - * it under the terms of the GNU General Public License as published by
  327.10 - * the Free Software Foundation, version 2 of the License.
  327.11 - *
  327.12 - * This program is distributed in the hope that it will be useful,
  327.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  327.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  327.15 - * GNU General Public License for more details.
  327.16 - *
  327.17 - * You should have received a copy of the GNU General Public License
  327.18 - * along with this program. Look for COPYING file in the top folder.
  327.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  327.20 - */
  327.21 -package org.apidesign.bck2brwsr.tck;
  327.22 -
  327.23 -class StaticUse {
  327.24 -    public static final Object NON_NULL = new Object();
  327.25 -    private StaticUse() {
  327.26 -    }
  327.27 -    
  327.28 -    public void instanceMethod() {
  327.29 -    }
  327.30 -
  327.31 -    public static int plus(int a, int b) {
  327.32 -        return a + b;
  327.33 -    }
  327.34 -}
   328.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/CRC32Test.java	Wed Feb 27 17:50:47 2013 +0100
   328.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   328.3 @@ -1,41 +0,0 @@
   328.4 -/**
   328.5 - * Back 2 Browser Bytecode Translator
   328.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   328.7 - *
   328.8 - * This program is free software: you can redistribute it and/or modify
   328.9 - * it under the terms of the GNU General Public License as published by
  328.10 - * the Free Software Foundation, version 2 of the License.
  328.11 - *
  328.12 - * This program is distributed in the hope that it will be useful,
  328.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  328.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  328.15 - * GNU General Public License for more details.
  328.16 - *
  328.17 - * You should have received a copy of the GNU General Public License
  328.18 - * along with this program. Look for COPYING file in the top folder.
  328.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  328.20 - */
  328.21 -package org.apidesign.bck2brwsr.vmtest.impl;
  328.22 -
  328.23 -import java.io.UnsupportedEncodingException;
  328.24 -import java.util.zip.CRC32;
  328.25 -import org.apidesign.bck2brwsr.vmtest.Compare;
  328.26 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  328.27 -import org.testng.annotations.Factory;
  328.28 -
  328.29 -/**
  328.30 - *
  328.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  328.32 - */
  328.33 -public class CRC32Test {
  328.34 -
  328.35 -    @Compare public long crc1() throws UnsupportedEncodingException {
  328.36 -        CRC32 crc = new CRC32();
  328.37 -        crc.update("Hello World!".getBytes("UTF-8"));
  328.38 -        return crc.getValue();
  328.39 -    }
  328.40 -    
  328.41 -    @Factory public static Object[] create() {
  328.42 -        return VMTest.create(CRC32Test.class);
  328.43 -    }
  328.44 -}
   329.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipEntryTest.java	Wed Feb 27 17:50:47 2013 +0100
   329.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   329.3 @@ -1,67 +0,0 @@
   329.4 -/**
   329.5 - * Back 2 Browser Bytecode Translator
   329.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   329.7 - *
   329.8 - * This program is free software: you can redistribute it and/or modify
   329.9 - * it under the terms of the GNU General Public License as published by
  329.10 - * the Free Software Foundation, version 2 of the License.
  329.11 - *
  329.12 - * This program is distributed in the hope that it will be useful,
  329.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  329.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  329.15 - * GNU General Public License for more details.
  329.16 - *
  329.17 - * You should have received a copy of the GNU General Public License
  329.18 - * along with this program. Look for COPYING file in the top folder.
  329.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  329.20 - */
  329.21 -package org.apidesign.bck2brwsr.vmtest.impl;
  329.22 -
  329.23 -import java.io.ByteArrayInputStream;
  329.24 -import java.io.IOException;
  329.25 -import java.io.InputStream;
  329.26 -import org.apidesign.bck2brwsr.emul.zip.FastJar;
  329.27 -import org.testng.annotations.Test;
  329.28 -import static org.testng.Assert.*;
  329.29 -
  329.30 -/**
  329.31 - *
  329.32 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  329.33 - */
  329.34 -@GenerateZip(name = "five.zip", contents = {
  329.35 -    "1.txt", "one",
  329.36 -    "2.txt", "duo",
  329.37 -    "3.txt", "three",
  329.38 -    "4.txt", "four",
  329.39 -    "5.txt", "five"
  329.40 -})
  329.41 -public class ZipEntryTest {
  329.42 -    @Test
  329.43 -    public void readEntriesEffectively() throws IOException {
  329.44 -        InputStream is = ZipEntryTest.class.getResourceAsStream("five.zip");
  329.45 -        byte[] arr = new byte[is.available()];
  329.46 -        int len = is.read(arr);
  329.47 -        assertEquals(len, arr.length, "Read fully");
  329.48 -        
  329.49 -        FastJar fj = new FastJar(arr);
  329.50 -        FastJar.Entry[] entrs = fj.list();
  329.51 -        
  329.52 -        assertEquals(5, entrs.length, "Five entries");
  329.53 -        
  329.54 -        for (int i = 1; i <= 5; i++) {
  329.55 -            FastJar.Entry en = entrs[i - 1];
  329.56 -            assertEquals(en.name, i + ".txt");
  329.57 -//            assertEquals(cis.cnt, 0, "Content of the file should be skipped, not read");
  329.58 -        }
  329.59 -        
  329.60 -        assertContent("three", fj.getInputStream(entrs[3 - 1]), "read OK");
  329.61 -        assertContent("five", fj.getInputStream(entrs[5 - 1]), "read OK");
  329.62 -    }
  329.63 -
  329.64 -    private static void assertContent(String exp, InputStream is, String msg) throws IOException {
  329.65 -        byte[] arr = new byte[512];
  329.66 -        int len = is.read(arr);
  329.67 -        String s = new String(arr, 0, len);
  329.68 -        assertEquals(exp, s, msg);
  329.69 -    }
  329.70 -}
   330.1 --- a/rt/vmtest/src/test/java/org/apidesign/bck2brwsr/vmtest/impl/ZipFileTest.java	Wed Feb 27 17:50:47 2013 +0100
   330.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   330.3 @@ -1,108 +0,0 @@
   330.4 -/**
   330.5 - * Back 2 Browser Bytecode Translator
   330.6 - * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
   330.7 - *
   330.8 - * This program is free software: you can redistribute it and/or modify
   330.9 - * it under the terms of the GNU General Public License as published by
  330.10 - * the Free Software Foundation, version 2 of the License.
  330.11 - *
  330.12 - * This program is distributed in the hope that it will be useful,
  330.13 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
  330.14 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  330.15 - * GNU General Public License for more details.
  330.16 - *
  330.17 - * You should have received a copy of the GNU General Public License
  330.18 - * along with this program. Look for COPYING file in the top folder.
  330.19 - * If not, see http://opensource.org/licenses/GPL-2.0.
  330.20 - */
  330.21 -package org.apidesign.bck2brwsr.vmtest.impl;
  330.22 -
  330.23 -import java.io.IOException;
  330.24 -import java.io.InputStream;
  330.25 -import java.util.Objects;
  330.26 -import java.util.zip.ZipEntry;
  330.27 -import java.util.zip.ZipInputStream;
  330.28 -import org.apidesign.bck2brwsr.core.JavaScriptBody;
  330.29 -import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
  330.30 -import org.apidesign.bck2brwsr.vmtest.Compare;
  330.31 -import org.apidesign.bck2brwsr.vmtest.Http;
  330.32 -import org.apidesign.bck2brwsr.vmtest.VMTest;
  330.33 -import org.testng.annotations.Factory;
  330.34 -
  330.35 -/**
  330.36 - *
  330.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
  330.38 - */
  330.39 -@GenerateZip(name = "readAnEntry.zip", contents = { 
  330.40 -    "my/main/file.txt", "Hello World!"
  330.41 -})
  330.42 -public class ZipFileTest {
  330.43 -    
  330.44 -    @Compare public String readAnEntry() throws IOException {
  330.45 -        InputStream is = ZipFileTest.class.getResourceAsStream("readAnEntry.zip");
  330.46 -        ZipInputStream zip = new ZipInputStream(is);
  330.47 -        ZipEntry entry = zip.getNextEntry();
  330.48 -        assertEquals(entry.getName(), "my/main/file.txt", "Correct entry");
  330.49 -
  330.50 -        byte[] arr = new byte[4096];
  330.51 -        int len = zip.read(arr);
  330.52 -        
  330.53 -        assertEquals(zip.getNextEntry(), null, "No next entry");
  330.54 -        
  330.55 -        final String ret = new String(arr, 0, len, "UTF-8");
  330.56 -        return ret;
  330.57 -    }
  330.58 -    
  330.59 -    @JavaScriptBody(args = { "res", "path" }, body = 
  330.60 -          "var myvm = bck2brwsr.apply(null, path);\n"
  330.61 -        + "var cls = myvm.loadClass('java.lang.String');\n"
  330.62 -        + "return cls.getClass__Ljava_lang_Class_2().getResourceAsStream__Ljava_io_InputStream_2Ljava_lang_String_2(res);\n"
  330.63 -    )
  330.64 -    private static native Object loadVMResource(String res, String...path);
  330.65 -
  330.66 -    @Http({
  330.67 -        @Http.Resource(path = "/readAnEntry.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip")
  330.68 -    })
  330.69 -    @BrwsrTest  public void canVmLoadResourceFromZip() throws IOException {
  330.70 -        Object res = loadVMResource("/my/main/file.txt", "/readAnEntry.jar");
  330.71 -        assert res instanceof InputStream : "Got array of bytes: " + res;
  330.72 -        InputStream is = (InputStream)res;
  330.73 -        
  330.74 -        byte[] arr = new byte[4096];
  330.75 -        int len = is.read(arr);
  330.76 -        
  330.77 -        final String ret = new String(arr, 0, len, "UTF-8");
  330.78 -
  330.79 -        assertEquals(ret, "Hello World!", "Can read the bytes");
  330.80 -    }
  330.81 -    
  330.82 -    @GenerateZip(name = "cpattr.zip", contents = { 
  330.83 -        "META-INF/MANIFEST.MF", "Manifest-Version: 1.0\n"
  330.84 -        + "Created-By: hand\n"
  330.85 -        + "Class-Path: realJar.jar\n\n\n"
  330.86 -    })
  330.87 -    @Http({
  330.88 -        @Http.Resource(path = "/readComplexEntry.jar", mimeType = "x-application/zip", content = "", resource="cpattr.zip"),
  330.89 -        @Http.Resource(path = "/realJar.jar", mimeType = "x-application/zip", content = "", resource="readAnEntry.zip"),
  330.90 -    })
  330.91 -    @BrwsrTest  public void understandsClassPathAttr() throws IOException {
  330.92 -        Object res = loadVMResource("/my/main/file.txt", "/readComplexEntry.jar");
  330.93 -        assert res instanceof InputStream : "Got array of bytes: " + res;
  330.94 -        InputStream is = (InputStream)res;
  330.95 -        
  330.96 -        byte[] arr = new byte[4096];
  330.97 -        int len = is.read(arr);
  330.98 -        
  330.99 -        final String ret = new String(arr, 0, len, "UTF-8");
 330.100 -
 330.101 -        assertEquals(ret, "Hello World!", "Can read the bytes from secondary JAR");
 330.102 -    }
 330.103 -    
 330.104 -    private static void assertEquals(Object real, Object exp, String msg) {
 330.105 -        assert Objects.equals(exp, real) : msg + " exp: " + exp + " real: " + real;
 330.106 -    }
 330.107 -    
 330.108 -    @Factory public static Object[] create() {
 330.109 -        return VMTest.create(ZipFileTest.class);
 330.110 -    }
 330.111 -}
   331.1 --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/0xfe	Wed Feb 27 17:50:47 2013 +0100
   331.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   331.3 @@ -1,1 +0,0 @@
   331.4   331.5 \ No newline at end of file
   332.1 --- a/rt/vmtest/src/test/resources/org/apidesign/bck2brwsr/tck/Resources.txt	Wed Feb 27 17:50:47 2013 +0100
   332.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
   332.3 @@ -1,1 +0,0 @@
   332.4 -Ahoj